数组名的明白,sizeof与strlen的区别

[复制链接]
发表于 2025-8-14 21:05:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次

一、size与strlen的区别
二、数组与指针题目剖析
2.0、重要结论
2.1、一维整型数组(sizeof)
2.2、一维字符数组 (常量字符串的strlen)
2.3、一维字符数组 (字符串的sizeof)
2.4、 一维字符数组 (字符串的strlen)
2.5、一维字符数组(指针变量sizeof)
2.6、一维字符数组(指针变量strlen)
2.7、 二维整型数组(sizeof)
 2.8、易混淆点
三、数组指针与指针数组
3.1、二者区别
3.2、指针数组(动态开发)
3.3、数组指针(静态二维数组)
3.3、常见误区


一、size与strlen的区别

     sizeof(关键字)     1:sizeof是操纵符      2:sizeof盘算操纵数所占内存的⼤⼩,单位是字节        3:不关注内存中存放什么数据        strlen(函数)     1:strlen是库函数,使⽤必要包含头⽂<string.h>     2:srtlen是求字符串⻓度的,统计的是 \0 之前字符的个数      3:关注内存中是否有   \0   ,如果没有   \0   ,就会连续往后找,可能会越界    二、数组与指针题目剖析

2.0、重要结论



  • sizeof(数组名) :这里的数组名指的是整个数组
  • &数组名           :这里的数组名指的是整个数组,取出的是地址
  • 反之代表的都是首元素的地址(X64->8    X86->4)
2.1、一维整型数组(sizeof)

  1. int main()
  2. {
  3.         int a[] = { 1,2,3,4 };
  4.         printf("%zd\n", sizeof(a)); //16,表示取出整个数组的大小
  5.         printf("%zd\n", sizeof(a + 0)); //8,表示首元素的地址大小
  6.         printf("%zd\n", sizeof(*a)); //4,表示首元素的值的sizeof
  7.         printf("%zd\n", sizeof(a + 1)); //8,表示第二个元素的地址大小
  8.         printf("%zd\n", sizeof(a[1])); //4,表示第二个元素的值的sizeof
  9.         printf("%zd\n", sizeof(&a)); //8,表示的是整个数组名的地址大小
  10.         printf("%zd\n", sizeof(*&a)); //16,*&抵消,即sizeof(a),表示取出整个数组的大小
  11.         printf("%zd\n", sizeof(&a + 1));//8,表示跳过整个数组之后的那个地址的大小
  12.         printf("%zd\n", sizeof(&a[0])); //8,表示首元素的地址大小
  13.         printf("%zd\n", sizeof(&a[0] + 1));//8,表示第二个元素的地址大小
  14.         return 0;
  15. }
复制代码
对于每一个盘算的表明都在对应的注释。
打印效果:

2.2、一维字符数组 (常量字符串的strlen)

  1. int main()
  2. {
  3.         //strlen参数是char*,从当前位置开始找'\0'
  4.         char arr[] = { 'a','b','c','d','e','f' }; //常量字符串,无'\0'
  5.         //printf("%zd\n", strlen(arr)); //error,从首元素出向后找'\0',无'\0'
  6.         //printf("%zd\n", strlen(arr + 0)); //error,从首元素出向后找'\0',无'\0'
  7.         //printf("%zd\n", strlen(*arr)); //非法访问,表示解引用出首元素,即ASCII为97,0x00000061处,构成非法访问
  8.         //printf("%zd\n", strlen(arr[1])); //非法访问,表示从第二个元素开始向后找,即ASCII为98,0x00000062处,构成非法访问
  9.         //printf("%zd\n", strlen(&arr));//error,表示从整个数组的起始地址向后找'\0'
  10.         //printf("%zd\n", strlen(&arr + 1)); //error,表示从整个数组末尾的下一个位置向后找'\0'
  11.         //printf("%zd\n", strlen(&arr[0] + 1));//error,表示从数组首元素地址向后找'\0'
  12.         return 0;
  13. }
复制代码
 对于每一个盘算的表明都在对应的注释。
2.3、一维字符数组 (字符串的sizeof)

  1. int main()
  2. {
  3.         char arr[] = "abcdef";
  4.         printf("%zd\n", sizeof(arr)); //7,表示计算整个数组的大小
  5.         printf("%zd\n", sizeof(arr + 0));//8 ,表示计算首元素地址的大小
  6.         printf("%zd\n", sizeof(*arr)); //1,表示计算'a'的大小
  7.         printf("%zd\n", sizeof(arr[1]));//1,表示计算'b'的大小
  8.         printf("%zd\n", sizeof(&arr)); //8,表示计算整个数组的地址大小
  9.         printf("%zd\n", sizeof(&arr + 1));//8,表示计算整个数组的下一个位置地址的大小
  10.         printf("%zd\n", sizeof(&arr[0] + 1));//8,表示计算第二个元素地址的大小
  11.         return 0;
  12. }
复制代码
 对于每一个盘算的表明都在对应的注释。
打印效果:

2.4、 一维字符数组 (字符串的strlen)

  1. int main()
  2. {
  3.         char arr[] = "abcdef";
  4.         printf("%zd\n", strlen(arr)); //6,表示计算整个数组的长度
  5.         printf("%zd\n", strlen(arr + 0));//6 ,表示计算数组从首元素地址开始的长度
  6.         //printf("%zd\n", strlen(*arr)); //非法访问,表示解引用出首元素,即ASCII为97,0x00000061处,构成非法访问
  7.         //printf("%zd\n", strlen(arr[1])); //非法访问,表示从第二个元素开始向后找,即ASCII为98,0x00000062处,构成非法访问
  8.         printf("%zd\n", strlen(&arr)); //6,表示计算数组从整个数组的地址开始的长度
  9.         //printf("%zd\n", strlen(&arr + 1)); //error,表示计算从整个数组下一个位置开始的长度
  10.         printf("%zd\n", strlen(&arr[0] + 1));//5,表示计算数组从第二个元素地址开始的长度
  11. }
复制代码
 对于每一个盘算的表明都在对应的注释。
打印效果:

2.5、一维字符数组(指针变量sizeof)

  1. int main()
  2. {
  3.         char* p = "abcdef"; //p是指针变量,指向第一个元素的地址
  4.         printf("%zd\n", sizeof(p)); //8,表示计算指针变量所指向'a'地址的大小
  5.         printf("%zd\n", sizeof(p + 1)); //8,表示计算指针变量所指向'b'地址的大小
  6.         printf("%zd\n", sizeof(*p)); //1,表示计算指针变量所指向内容'a'(char)的大小
  7.         printf("%zd\n", sizeof(p[0])); //1,表示计算指针变量所指向内容'a'(char)的大小
  8.         printf("%zd\n", sizeof(&p)); //8,表示计算指向p指针的指针变量的大小(二级指针)
  9.         printf("%zd\n", sizeof(&p + 1)); //8,表示计算指向p指针下一个位置的指针变量的大小(二级指针)
  10.         printf("%zd\n", sizeof(&p[0] + 1));//8,表示计算指针变量所指向'b'地址的大小
  11.         return 0;
  12. }
复制代码
 对于每一个盘算的表明都在对应的注释。
打印效果:

2.6、一维字符数组(指针变量strlen)

  1. int main()
  2. {
  3.         char* p = "abcdef";
  4.         printf("%zd\n", strlen(p)); //6,表示计算数组从'a'开始的长度
  5.         printf("%zd\n", strlen(p + 1));//5 ,表示计算数组从'b'开始的长度
  6.         //printf("%zd\n", strlen(*p)); //非法访问,表示解引用出首元素'a',即ASCII为97,0x00000061处,构成非法访问
  7.         //printf("%zd\n", strlen(p[0])); //非法访问,表示解取出首元素'a',即ASCII为97,0x00000061处,构成非法访问
  8.         //printf("%zd\n", strlen(&p)); //error,表示计算二级指针的长度
  9.         //printf("%zd\n", strlen(&p + 1)); //error,表示计算二级指针下一个位置的长度
  10.         printf("%zd\n", strlen(&p[0] + 1));//5,表示计算数组从'b'开始的长度
  11.         return 0;
  12. }
复制代码
对于每一个盘算的表明都在对应的注释。
打印效果:

2.7、 二维整型数组(sizeof)

  1. int main()
  2. {
  3.         //sizeof(数组名)  这里的数组名指的是整个数组
  4.         //&数组名         这里的数组名指的是整个数组,取出的是地址
  5.         //其它情况均为数组首元素的地址
  6.         int a[3][4] = { 0 };
  7.         printf("%zd\n", sizeof(a)); //48,计算的是整个数组的大小
  8.         printf("%zd\n", sizeof(a[0][0]));//4,计算的是整个数组的第一个元素(int)的大小
  9.         printf("%zd\n", sizeof(a[0])); //16,a[0]也是数组名(首行),计算的是整个第一行的大小
  10.         printf("%zd\n", sizeof(a[0] + 1)); //8,这里a[0]并没有单独放在sizeof里面,代表第一行的第一个元素的地址,再+1,即&a[0][1]
  11.         printf("%zd\n", sizeof(*(a[0] + 1))); //4,*&a[0][1],即计算a[0][1](int)的大小
  12.         printf("%zd\n", sizeof(a + 1)); //8,这里a并没有单独放在sizeof里面,代表第一行的地址,再+1,即&a[1]
  13.         printf("%zd\n", sizeof(*(a + 1))); //16,*&a[1],即计算a[1](int[4])的大小
  14.         printf("%zd\n", sizeof(&a[0] + 1)); //8,&a[0]即取出第一行的地址,再+1,计算第二行的地址,&a[1]
  15.         printf("%zd\n", sizeof(*(&a[0] + 1))); //16,*&a[1],即计算a[1](int[4])的大小
  16.         printf("%zd\n", sizeof(*a)); //16,这里的a并没有单独放在sizeof内,a为&a[0],*a为a[0],计算整个a[0]的大小
  17.         printf("%zd\n", sizeof(a[3]));//16,这里的a[3],即等价于a[0],a[1],a[2],并不造成越界的问题。计算的是类型int[4]
  18.         return 0;
  19. }
复制代码
对于每一个盘算的表明都在对应的注释。
打印效果:

 2.8、易混淆点

  1. a[][]    int(单个元素)
  2. a[0]    int[4](第一行,4个int的数组)
  3. a[0]     → int* (在表达式中退化为指针)
  4. a        int[3][4](整个二维数组)
  5. a        → int(*)[4](在表达式中退化为指向行的指针)
  6. int* arr[]
  7. int (*arr)[]
复制代码
举个例子:


  • 对于二维数组a[][]中的a[],他的数据类型是int[4],但汇编时间会退化成int*,也就是我们常明白的行指针,但本质上的类型并不是指针,绝不能当做指针数组来明白。
  • 而sizeof本质上盘算的是数据的类型,也并不会因为越界访问而报错。
  • 对于a[][]中而言,他的数据类型是int[3][4],但汇编时间会退化成int(*)[4],也就是我们常明白的数组指针,绝不能当做二级指针来明白。
三、数组指针与指针数组

3.1、二者区别


3.2、指针数组(动态开发)

  1. int *ptr_arr[3];  // 3 个 int* 组成的数组
  2. for (int i = 0; i < 3; i++) {
  3.     ptr_arr[i] = malloc(4 * sizeof(int)); // 每行 4 个 int
  4. }
  5. ptr_arr[1][2] = 10; // 访问第 2 行的第 3 个元素
复制代码
3.3、数组指针(静态二维数组)

  1. int a[3][4] = {0};
  2. int (*arr_ptr)[4] = a;  // 指向 a[0](第一行)
  3. arr_ptr[1][2] = 20;     // 访问 a[1][2]
复制代码
3.3、常见误区

   ❌ ​​int **p 和 int (*p)[4] 不是一回事!​​
  

  • int **p 适用于 ​​指针数组​​(动态分配)。
  • int (*p)[4] 适用于 ​​静态二维数组​​。
  ❌ ​​int *p[4] 和 int (*p)[4] 完全差别!​​
  

  • int *p[4] 是 ​​指针数组​​(4 个 int*)。
  • int (*p)[4] 是 ​​数组指针​​(指向 int[4])。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表