【C语言系列】深入理解指针(5)
深入理解指针(5)
- 一、sizeof和strlen的对比
- 1.1sizeof
- 1.2strlen
- 1.3sizeof和strlen的对比
- 二、数组和指针笔试题解析
- 2.1 一维数组
- 2.2 字符数组
- 2.2.1代码1:
- 2.2.2代码2:
- 2.2.3代码3:
- 2.2.4代码4:
- 2.2.5代码5:
- 2.2.6代码6:
- 2.3 二维数组
- 三、指针运算笔试题解析
- 3.1题目1:
- 3.2题目2:
- 3.3题目3:
- 3.4题目4:
- 3.5题目5:
- 3.6题目6:
- 3.7题目7:
- 四、总结
- 1. `sizeof`与`strlen`的区别
- 2. 数组和指针的关系
- 3. 字符数组与字符串
- 4. 指针运算
- 总结
一、sizeof和strlen的对比
1.1sizeof
sizeof是单目操作符(绝不是函数!!!),sizeof计算变量所占内存空间的大小的,单位是字节。
如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。
注:sizeof只关注占用内存空间的大小,不在乎内存中存放什么数据。
比如:
#inculde <stdio.h>int main(){int a = 10;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);printf("%d\n", sizeof(int));return 0;}
1.2strlen
strlen是C语言库函数,功能是求字符串长度。
函数原型是:
size_t strlen ( const char * str );
统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数。
注:strlen 函数会一直向后找 \0 字符,直到找到为止,所以可能存在越界查找。
代码如下:
#include <stdio.h>
int main()
{char arr1[3] = {'a', 'b', 'c'};char arr2[] = "abc";printf("%d\n", strlen(arr1));printf("%d\n", strlen(arr2));printf("%d\n", sizeof(arr1));printf("%d\n", sizeof(arr2));return 0;
}
运行结果如下:
1.3sizeof和strlen的对比
sizeof | strlen |
---|---|
1.sizeof是操作符 | 1.strlen是库函数,使用需要包含头文件string.h |
2.sizeof计算操作数所占内存的大小,单位是字节 | 2.strlen是求字符串长度的,统计的是\0之前字符的个数 |
3.不关注内存中存放什么数据 | 3.关注内存中是否有\0,如果没有\0,就会持续往后找,可能会越界 |
4.sizeof括号中有表达式的话,表达式是不参与计算的!!! |
用代码检验4,代码如下:
#include <stdio.h>
int main()
{
int a = 8;
short s = 4;
printf("%d\n",sizeof(s = a + 2));//2
printf("%d\n",s);//4
return 0;
}
运行结果如下:
那么为什么sizeof中的表达式不计算?
C语言是编译型语言,在编译期这个表达式并不会被执行,sizeof 运算的结果是在编译期间就已知的常数值,并不需要等到运行时才求解。因此,对于其中涉及到的操作数或者操作本身都不需要实际执行。
二、数组和指针笔试题解析
2.1 一维数组
*a == a[0] == *(a + 0)
数组名的理解:数组名是数组首元素(第一个元素)的地址。
但是有2个是例外:1.sizeof(数组名) —— 数组名表示整个数组,计算的是整个数组的大小,单位是字节。
2.&数组名 —— 数组名表示的是整个数组,取出的是整个数组的地址。
除此之外,所有的数组名是数组首元素(第一个元素)的地址。
笔试题代码和解析如下:
#include <stdio.h>
int main()
{
int a[] = {1,2,3,4};//数组有几个元素?//4
printf("%zd\n",sizeof(a));//16
printf("%zd\n",sizeof(a + 0));//a是首元素的地址 —— 类型是int*,a + 0还是首元素的地址,是地址大小就是4/8。
printf("%zd\n",sizeof(*a));//a是首元素的地址,*a是首元素,大小就是4个字节。
printf("%zd\n",sizeof(a + 1));//a是首元素地址,类型是int*,a + 1跳过1个整型,a + 1就是第二个元素的地址,是地址大小就是4/8。
printf("%zd\n",sizeof(a[1]));//a[1]就是第二个元素,大小是4个字节。
printf("%zd\n",sizeof(&a));//&a是数组的地址,数组的地址也是地址,是地址大小就是4/8字节。
printf("%zd\n",sizeof(*&a));//1.*&互相抵消了,等价于sizeof(a),16
//2.&a是数组的地址,类型是int(*)[4],对数组指针解引用访问的是数组,计算的是数组的大小,16
//char* —— 解引用访问的是char
//int* —— 解引用访问的是int
printf("%zd\n",sizeof(&a + 1));//&a + 1是跳过这个数组后的那个位置的地址,是地址大小就是4/8字节。
printf("%zd\n",sizeof(&a[0]));//首元素的地址,大小就是4/8字节。
printf("%zd\n",sizeof(&a[0] + 1));//&a[0] + 1 —— 数组第二个元素的地址,大小就是4/8字节。
return 0;
}
运行结果如下图:
2.2 字符数组
2.2.1代码1:
笔试题代码和解析如下:
#include <stdio.h>
int main()
{
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n",sizeof(arr));//数组名单独放在sizeof内部,计算的是数组的大小,单位为字节,6。
printf("%d\n",sizeof(arr + 0));//arr是数组名表示首元素的地址,arr + 0还是首元素的地址,是地址就是4/8字节。
printf("%d\n",sizeof(*arr));//arr是首元素的地址,*arr就是首元素,大小就是1个字节。
//*arr == arr[0] == *(arr + 0)
printf("%d\n",sizeof(arr[1]));//arr[1]是第二个元素,大小也是1个字节。
printf("%d\n",sizeof(&arr));//&arr是数组的地址,数组的地址也是地址,是地址大小就是4/8个字节。
//&arr —— char(*)[6]
printf("%d\n",sizeof(&arr + 1));//4/8个字节,&arr + 1,跳过整个数组,指向了数组后边的空间。
printf("%d\n",sizeof(&arr[0] + 1));//第二个元素的地址,是地址就是4/8个字节。
return 0;
}
运行结果如下图:
2.2.2代码2:
笔试题代码和解析如下:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n",strlen(arr));//arr是首元素的地址,数组中没有\0,就会导致越界访问,结果就是随机的。
printf("%d\n",strlen(arr + 0));//arr + 0是数组首元素的地址,数组中没有\0,就会导致越界访问,结果就是随机的。
printf("%d\n",strlen(*arr));//arr是首元素的地址,*arr是首元素,就是'a','a'的ASCII码值是97,就相当于97作为地址传递给了strlen,strlen得到的就是野指针,代码是有问题的。
printf("%d\n",strlen(arr[1]));//arr[1] —— 'b' —— 98,传给strlen函数也是错误的。
printf("%d\n",strlen(&arr));//&arr是数组的地址,起始位置是数组的第一个元素的位置,随机值。
printf("%d\n",strlen(&arr + 1));//随机值。
printf("%d\n",strlen(&arr[0] + 1));//从第二个元素开始向后统计的,得到的也是随机值。
return 0;
}
运行结果如下图:
2.2.3代码3:
笔试题代码和解析如下:
#include <stdio.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n",sizeof(arr));//7,计算的是数组总大小,数组名单独放在sizeof内部。
printf("%d\n",sizeof(arr + 0));//arr表示数组首元素的地址,arr + 0还是首元素的地址,4/8字节。
printf("%d\n",sizeof(*arr));//arr表示数组首元素的地址,*arr是首元素,大小是1字节。
printf("%d\n",sizeof(arr[1]));//arr[1]是第二个元素,大小是1个字节。
printf("%d\n",sizeof(&arr));//&arr是数组的地址,是地址就是4/8字节。
printf("%d\n",sizeof(&arr + 1));//&arr是数组的地址,是地址就是4/8字节。
printf("%d\n",sizeof(&arr[0] + 1));//&arr是数组的地址,+1跳过整个数组,还是地址,是地址就是4/8字节。
return 0;
}
运行结果如下图:
2.2.4代码4:
笔试题代码和解析如下:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n",strlen(arr));//6
printf("%d\n",strlen(arr + 0));//arr首元素的地址,arr + 0还是首元素的地址,向后统计在\0之前的字符个数。//6
printf("%d\n",strlen(*arr));//'a' —— 97,出错。
printf("%d\n",strlen(arr[1]));//'b' —— 98.出错。
printf("%d\n",strlen(&arr));//&arr是数组的地址,也是从数组第一个元素开始向后找,6。
printf("%d\n",strlen(&arr + 1));//随机值。
printf("%d\n",strlen(&arr[0] + 1));//5
//&arr —— char(*)[7]
//size_t strlen(const char*s);
return 0;
}
运行结果如下图:
2.2.5代码5:
笔试题代码和解析如下:
#include <stdio.h>
int main()
{
const char*p = "abcdef";
printf("%d\n",sizeof(p));//p是指针变量,我们计算的是指针变量的大小,4/8个字节。
printf("%d\n",sizeof(p + 1));//p + 1是b的地址,是地址大小就是4/8个字节。
printf("%d\n",sizeof(*p));//p的类型是char*,*p就是char类型了,1个字节。
printf("%d\n",sizeof(p[0]));//1.p[0]->*(p + 0)->*p->'a',大小1个字节。
//1.把常量字符串想象成数组。
//2.p可以理解为数组名,p[0],就是首元素。
printf("%d\n",sizeof(&p));//取出的是p的地址,地址的大小就是4/8个字节。
printf("%d\n",sizeof(&p + 1));//&p + 1是跳过p指针变量后的地址,地址的大小是4/8个字节。
printf("%d\n",sizeof(&p[0] + 1));//4/8,取出首元素的地址,+1是第二个字符的地址。
return 0;
}
运行结果如下图:
2.2.6代码6:
笔试题代码和解析如下:
#include <stdio.h>
#include <string.h>
int main()
{
char*p ="abcdef";
printf("%d\n",strlen(p));//6
printf("%d\n",strlen(p + 1));//5
printf("%d\n",strlen(*p));//*p就是'a' —— 97,err
printf("%d\n",strlen(p[0]));//p[0]->*(p + 0)->*p//err
printf("%d\n",strlen(&p));//&p是指针变量p的地址,和字符串“abcdef”关系就不大了,从p这个指针变量的起始位置开始向后数的,p变量存放的地址是什么,不知道,所以答案是随机值。
printf("%d\n",strlen(&p + 1));//随机值
printf("%d\n",strlen(&p[0] + 1));//5
return 0;
}
运行结果如下图:
2.3 二维数组
二维数组笔试题代码和解析如下:
#include <stdio.h>
int main()
{
int a[3][4] = {0};
printf("%d\n",sizeof(a));//a是数组名,单独放在sizeof内部,计算的是数组的大小,单位是字节 —— 48 = 3*4*sizeof(int)。
printf("%d\n",sizeof(a[0][0]));//a[0][0]第一行第一个元素,大小是4个字节。
printf("%d\n",sizeof(a[0]));//a[0]是第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的总大小16个字节。
printf("%d\n",sizeof(a[0] + 1));//a[0]并没有单独放在sizeof内部,所以这里的数组名a[0]就是数组首元素的地址,即a[0]->&a[0][0],+1后是&a[0][1]的地址,大小是4/8个字节。
printf("%d\n",sizeof(*(a[0] + 1)));//第一行第一个元素,大小是4
printf("%d\n",sizeof(a + 1));//a作为数组名并没有单独放在sizeof内部,a表示数组首元素的地址,是二维数组首元素的地址,也就是第一行的地址,a + 1,跳过一行,指向了第二行,a + 1是第二行的地址,a + 1是数组指针,是地址大小就是4/8个字节。
printf("%d\n",sizeof(*(a + 1)));//1.a + 1是第二行的地址,*(a + 1)就是第二行,计算的是第二行的大小 —— 16。2.*(a + 1) == a[1],a[1]是第二行的数组名,sizeof(*(a + 1))就相当于sizeof(a[1]),意思就是把第二行的数组名单独放在sizeof内部,计算的是第二行的大小。
printf("%d\n",sizeof(&a[0] + 1));//a[0]是第一行的数组名,&a[0]取出的就是数组的地址,就是第一行的地址,&a[0] + 1就是第二行的地址,是地址大小就是4/8字节。
printf("%d\n",sizeof(*(&a[0] + 1)));//对第二行地址解引用,访问的就是第二行,大小是16个字节。
printf("%d\n",sizeof(*a));//a作为数组名并没有单独放在sizeof内部,a表示数组首元素的地址,是二维数组首元素的地址,也就是第一行的地址,*a就是第一行,计算的就是第一行的大小,16个字节。
printf("%d\n",sizeof(a[3]));//a[3]无需真实存在,仅仅通过类型的推断就能算出长度,a[3]是第四行的数组名,单独放在sizeof内部,计算第四行的大小,16个字节。
//sizeof(int);//4
//sizeof(3+5);//4
return 0;
}
运行结果如下图:
三、指针运算笔试题解析
3.1题目1:
指针运算笔试题代码和解析如下:
#include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int*ptr = (int*)(&a + 1);//&a —— int(*)[5]
printf("%d %d",*(a + 1),*(ptr - 1));//ptr跳过了原来a数组指向下一个位置,*(ptr-1)访问的就是数组a中的5。
return 0;
}
运行结果如下图:
3.2题目2:
在X86(32位)环境下,假设结构体的大小是20个字节,程序输出的结果是什么?
指针运算笔试题代码和解析如下:
#include <stdio.h>
struct Test
{
int Num;
char*PcName;
short sDate;
char cha[2];
short sBa[4];
}*p = (struct Test*)0x100000;//结构体指针+1,跳过一个结构体;整型值+1,就是+1。
//指针+-整数
int main()
{
printf("%p\n",p + 0x1);//0x100000 + 20 -> 00100014
printf("%p\n",(unsigned long)p + 0x1);//0x100000 + 1 ->0x100001 -> 00100001
printf("%p\n",(unsigned int*)p + 0x1);//0x100000 + 4 -> 0x100004 -> 00100004
return 0;
}
运行结果如下图:
3.3题目3:
指针运算笔试题代码和解析如下:
#include <stdio.h>
int main()
{
int a[3][2] = {(0,1),(2,3),(4,5)};//1 3 5//初始化
int*p;
p = a[0];//&a[0][0];
printf("%d",p[0]);//1//*(p + 0) -> *p
return 0;
}
运行结果如下图:
3.4题目4:
假设环境是X86环境,程序的输出结果是什么?
指针运算笔试题代码和解析如下:
#include <stdio.h>
int main()
{//%d —— 是打印有符号的整数
//%p —— 是打印地址的
int a[5][5];//a —— 类型是:int(*)[5]
int(*p)[4];//p —— 类型是:int(*)[4]//p是一个数组指针,p指向的数组是4个整型元素的
p = a;//类型的差异 —— 警告
printf("%p,%d\n",&p[4][2] - &a[4][2],&p[4][2] - &a[4][2]);//FFFFFFFC,-4
return 0;
}
//指针-指针绝对值得到的是指针和指针之间的元素个数
运行结果如下图:
3.5题目5:
指针运算笔试题代码和解析如下:
#include <stdio.h>
int main()
{
int aa[2][5] = {1,2,3,4,5,6,7,8,9,10};
int*ptr1 = (int*)(&aa + 1);
int*ptr2 = (int*)(*(aa + 1));
printf("%d %d",*(ptr1 - 1),*(ptr2 - 1));//10 5
return 0;
}
//*(aa + 1)->aa[1],aa[1]是第二行的数组名,数组名表示首元素的地址。
//aa[1]也是&aa[1][0]
//*(aa + 1)->aa[1],&aa[1]->第二行的地址
//sizeof(aa[1])->计算的是第二行的大小
运行结果如下图:
3.6题目6:
指针运算笔试题代码和解析如下:
#include <stdio.h>
int main()
{
char*a[] = {"work","at","alibaba"};//a是指针数组
char**pa = a;
pa++;
printf("%s\n",*pa);//at//%s是打印字符串,给一个地址,从这个地址向后打印字符串,直到\0
return 0;
}
画图分析:
运行结果如下图:
3.7题目7:
指针运算笔试题代码和解析如下:
#include <stdio.h>
int main()
{
char*c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c + 3,c + 2, c + 1,c};
char***cpp = cp;
printf("%s\n",**++cpp);//POINT
printf("%s\n",*--*++cpp + 3);//ER
printf("%s\n",*cpp[-2] + 3);//**(cpp - 2) + 3//ST
printf("%s\n",cpp[-1][-1] + 1);//*c*(cpp-1) - 1//EW
return 0;
}
运行结果如下图:
四、总结
本文深入探讨了C语言中关于sizeof
、strlen
、数组和指针的一些基础概念,并通过代码示例进行了详细的讲解。以下是对主要内容的总结:
1. sizeof
与strlen
的区别
sizeof
是一个运算符,用于计算变量或类型所占的内存空间大小,单位是字节。它与数据存储内容无关,只关注内存的占用。例如,sizeof(int)
会返回一个整数类型的大小,而sizeof(a)
会返回数组a
的总字节数。需要注意的是,sizeof
中的表达式不会被计算,仅仅是编译时确定的常量。
与此不同,strlen
是C标准库中的一个函数,用于计算以'\0'
(空字符)结尾的字符串的长度。它统计的是字符串中的字符个数,而不包括'\0'
字符。因此,strlen
在处理字符串时,必须确保字符串正确地以'\0'
结尾,否则可能导致越界访问。
2. 数组和指针的关系
数组和指针是C语言中常见的概念,它们密切相关。数组名通常被认为是指向数组首元素的指针。通过数组名,可以访问数组的元素,但是数组名和指针在某些情况下也有所不同。例如,sizeof(a)
计算的是整个数组的大小,而sizeof(a + 1)
计算的是数组中某个元素的指针大小。此外,数组名也可以通过&a
表示整个数组的地址,&a[0]
表示数组首元素的地址。
3. 字符数组与字符串
字符数组在内存中的存储方式可能导致不同的行为。在没有'\0'
结尾的情况下,使用strlen
函数可能会导致越界访问,进而产生随机结果。通过具体的代码示例,文章展示了不同数组类型在使用sizeof
和strlen
时的差异,特别是字符数组和字符串常量。
4. 指针运算
指针运算是C语言中强大的功能之一。指针可以进行加减操作,指向内存中的不同位置。通过对数组指针进行运算,可以访问数组中的不同元素。指针间的运算遵循指针类型的大小,比如int*
指针加1时会跳过一个int
类型的大小,指向下一个int
类型的数据。文章通过一系列例子展示了指针和数组在内存中的操作,包括指针的解引用、指针数组的运算等。
总结
本篇文章深入分析了sizeof
、strlen
、数组与指针等概念,并通过一系列代码示例加深了对这些概念的理解。对于初学者来说,掌握这些基础知识是学习C语言的关键。文章不仅揭示了这些基本概念的使用方法,还通过具体例子帮助理解如何避免常见的错误,如越界访问和指针运算中的误解。
相关文章:
【C语言系列】深入理解指针(5)
深入理解指针(5) 一、sizeof和strlen的对比1.1sizeof1.2strlen1.3sizeof和strlen的对比 二、数组和指针笔试题解析2.1 一维数组2.2 字符数组2.2.1代码1:2.2.2代码2:2.2.3代码3:2.2.4代码4:2.2.5代码5&#…...
为什么使用nohup 和 启动的python脚本,日志没有在nohup.out中
当你使用 nohup 和 & 启动 Python 脚本时,输出通常会被重定向到 nohup.out 文件,但是有几个原因可能导致日志没有出现在这个文件中: Python 程序的输出被重定向了: 如果你的 Python 脚本中使用了 sys.stdout 或 sys.stderr 进…...
MySQL的存储引擎对比(InnoDB和MyISAM)
InnoDB 特点: 事务支持:InnoDB 是 MySQL 默认的事务型存储引擎,支持 ACID(原子性、一致性、隔离性、持久性)事务。行级锁定:支持行级锁,能够并发执行查询和更新操作,提升多用户环境…...
uniapp访问django目录中的图片和视频,2025[最新]中间件访问方式
新建中间件, middleware.py 匹配,以/cover_image/ 开头的图片 匹配以/episode_video/ 开头的视频 imageSrc: http://192.168.110.148:8000/cover_image/12345/1738760890657_mmexport1738154397386.jpg, videoSrc: http://192.168.110.148:8000/episode_video/12345/compres…...
Python递归复习题
寒假打卡第二十一天,当前mit6.100L进度(16/26) ,今天补一下递归复习题。 问题1:编写一个递归程序来计算正和n(n-2)(n-4)的整数(直到且不包括n-x<0) def sum_series(n…...
2025 年前端开发趋势展望,开启新征程
新年伊始,作为一名深耕 Web 前端开发领域的博主,我迫不及待地想和大家分享我对 2025 年前端开发趋势的洞察。过去一年里,前端领域的技术创新和变革令人目不暇接,而新的一年,更是充满无限可能。 框架与工具的持续演进 …...
90,【6】攻防世界 WEB Web_php_unserialize
进入靶场 进入靶场 <?php // 定义一个名为 Demo 的类 class Demo { // 定义一个私有属性 $file,默认值为 index.phpprivate $file index.php;// 构造函数,当创建类的实例时会自动调用// 接收一个参数 $file,用于初始化对象的 $file 属…...
Redis --- 使用GEO实现经纬度距离计算
什么是GEO? Spring Boot 项目中可以通过 Spring Data Redis 来使用 Redis GEO 功能,主要通过 RedisTemplate 和 GeoOperations 接口来操作地理位置数据。 Service public class GeoService {Autowiredprivate RedisTemplate<String, Object> red…...
同步 CDC
同步 CDC 当设计包括来自同一 MMCM/PLL 的时钟之间的同步 CDC 路径时,您可以使用以下技术来更好地控制时钟插入延迟和 时滞,并因此控制这些路径上的松弛。 重要提示: 如果 CDC 路径在源自不同 MMCM/PLL 的时钟之间,则跨越 …...
Linux环境下载Ollama慢或卡顿解决方案
一、下载方式 官方下载方式是到ollama官网下载ollama: https://ollama.com/ 复制下载链接执行: curl -fsSL https://ollama.com/install.sh | sh二、卡顿现象 执行后经常会出现下载失败或者进度条特别慢的情况,甚至直接退出下载: 三、…...
生成式AI安全最佳实践 - 抵御OWASP Top 10攻击 (下)
今天小李哥将开启全新的技术分享系列,为大家介绍生成式AI的安全解决方案设计方法和最佳实践。近年来生成式 AI 安全市场正迅速发展。据IDC预测,到2025年全球 AI 安全解决方案市场规模将突破200亿美元,年复合增长率超过30%,而Gartn…...
2025年家用音响市场分析:潜力无限,音质为王的新纪元
引言:音质革命引领市场新风尚 在数字化浪潮的推动下,家用音响市场正经历一场前所未有的变革,其增长潜力犹如破晓之光,照亮了音频技术的未来之路。随着消费者对高品质生活追求的不断提升,以及对智能家居生态融合的日益…...
neo4j-在Linux中安装neo4j
目录 切换jdk 安装neo4j 配置neo4j以便其他电脑可以访问 切换jdk 因为我安装的jdk是1.8版本的,而我安装的neo4j版本为5.15,Neo4j Community 5.15.0 不支持 Java 1.8,它要求 Java 17 或更高版本。 所以我需要升级Java到17 安装 OpenJDK 17 sudo yu…...
AI 场景下,函数计算 GPU 实例模型存储最佳实践
作者:有松 当前,函数计算 FC 已被广泛应用在各种 AI 场景下,函数计算支持通过使用容器镜像部署 AI 推理应用,并且提供多种选项来访问训练好的模型。为了帮助开发者高效地在函数计算上部署 AI 推理应用,并快速解决不同…...
股指入门:股指期货是什么意思?在哪里可以做股指期货交易?
股指期货是一种以股票指数为标的物的期货合约,也可以称为股票指数期货或期指。 股指期货是什么意思? 股指期货是一种金融衍生品,其标的资产是股票市场上的股指,例如标普500指数、道琼斯工业平均指数、上证50指数等。 股指期货允…...
【分布式理论六】分布式调用(4):服务间的远程调用(RPC)
文章目录 一、RPC 调用过程二、RPC 动态代理:屏蔽远程通讯细节1. 动态代理示例2. 如何将动态代理应用于 RPC 三、RPC 序列化四、RPC 协议编码1. 协议编码的作用2. RPC 协议消息组成 五、RPC 网络传输1. 网络传输流程2. 关键优化点 一、RPC 调用过程 RPC(…...
aliyun 的 ip 设置方法
aliyun 的 ip 设置方法 阿里云:网络编程 bind:cannot assign requested address errno:99 问题。 公网IP,,弹性公网IP,主私网IP 1. 公网IP, --> NAT --> 主私网IP ,设置方法: 服务器端 ip 为&…...
ASP.NET Core分布式缓存
目录 分布式缓存 概述 IDistributedCache接口中定义的主要方法及主要的扩展方法 用什么做缓存服务器 使用 封装分布式缓存操作 分布式缓存 概述 分布式系统中,内存缓存不满足要求的话,把缓存数据保存到专门的缓存服务器,所有Web应用通…...
【CUDA】内存模型
目录 一、Programmable 1.1 寄存器(Registers) 1.2 本地内存(Local Memory) 1.3 共享内存(shared Memory) 1.4 常量内存(Constant Memory) 1.5 全局内存(Global Memory) 1.6 纹理内存(Textrue Memory) 1.7 总结 二、Cache(Non-programmable) 三、固定内存 四、零拷贝…...
使用Pygame制作“吃豆人”游戏
本篇博客展示如何使用 Python Pygame 编写一个简易版的“吃豆人(Pac-Man)” 风格游戏。这里我们暂且命名为 Py-Man。玩家需要控制主角在一个网格地图里移动、吃掉散布在各处的豆子,并躲避在地图中巡逻的幽灵。此示例可帮助你理解网格地图、角…...
Pyecharts系列课程04——折线图/面积图(Line)
本章我们学习在Pyecharts中折线图(Line)的使用。折线图通用应用于数据的趋势分析。 折线图 我们现在有两组数据,x_data是2024年的月份,y_data为对应张三甲每个月的用电量。 # 家庭每月用电量趋势 x_data ["1月", &q…...
mysql 学习10 多表查询 -多表关系,多表查询
多表关系 一对多 多对多 创建学生表 #多对多表 学生选课系统create table student(id int primary key auto_increment comment 主键ID,name varchar(64) comment 姓名,studentnumber varchar(10) comment 学号 )comment 学生表;insert into student(id,name,studentnumber)va…...
lambda 表达式详解
lambda 表达式详解 lambda 表达式详解基本语法示例代码及详细解释1. 简单的lambda表达式2. 带参数的lambda表达式3. 捕获外部变量4. 使用mutable关键字修改捕获的变量5. 按引用捕获外部变量6. 自动推导返回类型 捕获列表的几种形式总结 Lambda表达式的常用的应用场景࿱…...
从0开始达芬奇(3.5)
媒体优化 顾名思义就是降低分辨率等来使素材的回放更加流畅。(在低配电脑上也可以流畅运行) ⭐方法一:(一般使用第二种) 播放→代理模式→二分之一或者四分之一 ⭐⭐⭐方法二:优化媒体文件(简…...
【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据
一、下载z-paing插件 注意下载下载量最多的这个 进入Hbuilder以后点击“确定” 插件的官方文档地址: https://z-paging.zxlee.cn 二、z-paging插件的使用 在文档中向下滑动,会有使用方法。 使用z-paging标签将所有的内容包起来 配置标签中的属性 在s…...
Ubuntu20.04 本地部署 DeepSeek-R1
一、下载ollama 打开 ollama链接,直接终端运行提供的命令即可。如获取的命令如下: curl -fsSL https://ollama.com/install.sh | sh确保是否安装成功可在终端输入如下命令: ollama -v注意: 如遇到Failed to connect to github.…...
Linux 设备驱动分类(快速理解驱动架构)
Linux 设备驱动分类(快速理解驱动架构) 在 Linux 设备驱动开发中,最基础的概念就是 设备驱动的分类。 Linux 设备驱动主要分为 字符设备、块设备和网络设备,它们分别对应不同类型的硬件资源。 理解这些分类,不仅能帮助…...
Java语法糖详解
前言 在现代编程语言的发展历程中,语法糖(Syntactic Sugar)作为一种提升代码可读性和开发效率的重要特性,已经成为语言设计的重要组成部分。Java作为一门成熟且广泛应用的编程语言,在其长期演进过程中,语法…...
567.字符串的排列
目录 一、题目二、思路2.1 解题思路2.2 代码尝试2.3 疑难问题 三、解法四、收获4.1 心得4.2 举一反三 一、题目 二、思路 2.1 解题思路 用两个哈希表比较来判断。s1的哈希表是否与s2相同。在窗口滑动过程中,用哈希表来维护。 2.2 代码尝试 class Solution { pub…...
DB2和mysql关于表和索引是否需要reorg的研究
DB2: DB2有个reorgchk的命令,是从SYSSTAT.TABLES和syscat.indexes这两个系统表中查表和索引的信息,并给出是否需要reorg表和索引的建议。 [db2inst1t3-ucm-ucm-rdb ~]$ db2 reorgchk CURRENT STATISTICS on table DB2ADMIN.ACAGENTTREE Ta…...
【Linux系统编程】:自旋锁,读写锁
文章目录 前言1. POSIX自旋锁1.1.定义自旋锁1.2.初始化1.3. 加锁1.4. 尝试加锁操作1.5. 解锁操作1.6. 销毁操作1.7.示例1.8.优缺点优点缺点 1.9.适用场景 2. 读写锁2.1 读写锁的工作原理2.2 读写模型2.3 常用接口2.3.1 定义锁并初始化2.3.2 申请读锁2.3.3 申请写锁2.3.4 解锁2.…...
位运算及常用技巧
涉及位运算的运算符如下表所示: 位运算的运算律: 负数的位运算 首先,我们要知道,在计算机中,运算是使用的二进制补码,而正数的补码是它本身,负数的补码则是符号位不变,其余按位取反…...
Chrome 浏览器:互联网时代的浏览利器
Chrome 浏览器:互联网时代的浏览利器 引言 在互联网时代,浏览器已经成为我们日常生活中不可或缺的工具。作为全球最受欢迎的浏览器之一,Chrome 浏览器凭借其出色的性能、丰富的扩展程序和简洁的界面,赢得了广大用户的喜爱。本文…...
web-文件上传-CTFHub
前言 在众多的CTF平台当中,作者认为CTFHub对于初学者来说,是入门平台的不二之选。CTFHub通过自己独特的技能树模块,可以帮助初学者来快速入门。具体请看官方介绍:CTFHub。 作者更新了CTFHub系列,希望小伙伴们多多支持…...
【react】react面试题
react面试题 对 React 的理解、特性 react18有哪些更新 JSX是什么 解释为什么浏览器不能读取jsx ReactNative中,如何解决8081端口被占用而提示无法访问的问题? React 生命周期 react事件机制 react 组件传值 React改变state的方式 re…...
逐笔成交逐笔委托Level2高频数据下载和分析:20250206
Level2逐笔成交逐笔委托数据分享下载 通过Level2逐笔成交和逐笔委托这种每一笔的毫秒级别的数据可以分析出很多有用的点,包括主力意图,虚假动作,让任何操作无所遁形。适合交易大师来分析主力规律,也适合人工智能领域的机器学习&a…...
__cvta_generic_to_shared
一 测试代码 #include <cuda_runtime.h> #include <cstdio> #include <cstdint>__global__ void test_cp_async(int* __restrict__ A,int* __restrict__ B){int tid = threadIdx.x;A[tid] = tid;__shared__ int smem[32];size_t smemAddr = __cvta_generic_…...
C++学习——缺省参数、重载函数、引用
目录 前言 一、缺省参数 1.1概念 1.2写法 1.3半缺省 1.4使用 二、重载函数 2.1.概念 2.2类型 2.3参数 2.4顺序 2.5问题 2.6原理 三、引用 1、引用是什么? 2、引用的使用方法 3、引用特性 1、引用在定义的时候必须要初始化 2、一个变量会有多个引用…...
docker-compose 配置nginx
前言 前端打包的dist文件在宿主机,nginx运行在docker-compose 问题 nginx.conf 在本地配置可以生效,但是链接到容器就报错 基于本地的nginx运行,本地nginx.conf 如下 server {listen 8081;location / {root /usr/local/software/testweb/…...
LQB(0)-python-基础知识
一、Python开发环境与基础知识 python解释器:用于解释python代码 方式: 1.直接安装python解释器 2.安装Anaconda管理python环境 python开发环境:用于编写python代码 1.vscode 2.pycharm # 3.安装Anaconda后可以使用网页版的jupyter n…...
【C语言】指针运算与数组关系:详细分析与实例讲解
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 💯前言💯1. 指针的基础运算1.1 指针的加减运算1.2 指针加整数与指针减整数1.3 指针与指针的运算 💯2. 指针的实际应用:模拟 strlen 函数2.1 使用指针模拟…...
C++数组
指针,是C数组工作方式的基础。 数组,基本上是元素的集合。按特定的顺序排列的一堆东西。 C数组,就是表示一堆的变量组成的集合。一般是一行相同类型的变量。 例子: #include <iostream> int main() {int example[5];exa…...
OSPF基础(2)
一、LSA的头部 LSA是OSPF的一个核心内容,如果没有LSA,OSPF是无法描述网络的拓扑结构及网段信息的,也无法传递路由信息,更加无法正常工作,在OSPFV2中,需要我们掌握的主要有6种。 LSA头部一共20byte,每个字段…...
DeepSeek R1 简单指南:架构、训练、本地部署和硬件要求
DeepSeek 的 LLM 推理新方法 DeepSeek 推出了一种创新方法,通过强化学习 (RL) 来提高大型语言模型 (LLM) 的推理能力,其最新论文 DeepSeek-R1 对此进行了详细介绍。这项研究代表了我们如何通过纯强化学习来增强 LLM 解决复杂问题的能力,而无…...
javaEE-6.网络原理-http
目录 什么是http? http的工作原理: 抓包工具 fiddler的使用 HTTP请求数据: 1.首行:编辑 2.请求头(header) 3.空行: 4.正文(body) HTTP响应数据 1.首行:编辑 2.响应头 3.空行: 4.响应正文…...
把bootstrap5.3.3整合到wordpress主题中的方法
以下是将 Bootstrap 5.3.3 整合到 WordPress 主题中的方法: 下载 Bootstrap 文件:从 Bootstrap 官网下载最新的 5.3.3 版本的 CSS 和 JavaScript 文件。 上传文件到主题目录:将下载的 CSS 文件上传到 WordPress 主题文件夹中的 /css 文件夹…...
深度整理总结MySQL——Buffer Pool工作原理
Buffer Pool工作原理 前言为什么会有Buffer PoolBuffer Pool介绍Buffer Pool有多大Buffer Pool缓存什么呢Buffer Pool碎片空间查询一条记录,就只需要缓冲一条记录吗 如何管理Buffer Pool如何管理空闲页如何管理脏页如何提高缓存命中率 LRU带来的问题预读失效Buffer …...
langchain教程-9.Retriever/检索器
前言 该系列教程的代码: https://github.com/shar-pen/Langchain-MiniTutorial 我主要参考 langchain 官方教程, 有选择性的记录了一下学习内容 这是教程清单 1.初试langchain2.prompt3.OutputParser/输出解析4.model/vllm模型部署和langchain调用5.DocumentLoader/多种文档…...
凝思60重置密码
凝思系统重置密码 - 赛博狗尾草 - 博客园 问题描述 凝思系统进入单用户模式,在此模式下,用户可以访问修复错误配置的文件。也可以在此模式下安装显卡驱动,解决和已加载驱动的冲突问题。 适用范围 linx-6.0.60 linx-6.0.80 linx-6.0.100…...
指针基础知识1
1.内存和地址 1.案例 我们可以借助一个生活在的案例来熟悉电脑中内存和地址的关系: 假设有⼀栋宿舍楼,把你放在楼里,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩, 如果想找到你,…...