欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 数组名的理解,sizeof与strlen的区别

数组名的理解,sizeof与strlen的区别

2025/10/17 0:17:43 来源:https://blog.csdn.net/2401_87671334/article/details/148021250  浏览:    关键词:数组名的理解,sizeof与strlen的区别

目录

一、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)

int main()
{int a[] = { 1,2,3,4 }; printf("%zd\n", sizeof(a)); //16,表示取出整个数组的大小printf("%zd\n", sizeof(a + 0)); //8,表示首元素的地址大小printf("%zd\n", sizeof(*a)); //4,表示首元素的值的sizeofprintf("%zd\n", sizeof(a + 1)); //8,表示第二个元素的地址大小printf("%zd\n", sizeof(a[1])); //4,表示第二个元素的值的sizeofprintf("%zd\n", sizeof(&a)); //8,表示的是整个数组名的地址大小printf("%zd\n", sizeof(*&a)); //16,*&抵消,即sizeof(a),表示取出整个数组的大小printf("%zd\n", sizeof(&a + 1));//8,表示跳过整个数组之后的那个地址的大小printf("%zd\n", sizeof(&a[0])); //8,表示首元素的地址大小printf("%zd\n", sizeof(&a[0] + 1));//8,表示第二个元素的地址大小return 0;
}

对于每一个计算的解释都在对应的注释。

打印结果:

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

int main()
{//strlen参数是char*,从当前位置开始找'\0'char arr[] = { 'a','b','c','d','e','f' }; //常量字符串,无'\0'//printf("%zd\n", strlen(arr)); //error,从首元素出向后找'\0',无'\0'//printf("%zd\n", strlen(arr + 0)); //error,从首元素出向后找'\0',无'\0'//printf("%zd\n", strlen(*arr)); //非法访问,表示解引用出首元素,即ASCII为97,0x00000061处,构成非法访问//printf("%zd\n", strlen(arr[1])); //非法访问,表示从第二个元素开始向后找,即ASCII为98,0x00000062处,构成非法访问//printf("%zd\n", strlen(&arr));//error,表示从整个数组的起始地址向后找'\0'//printf("%zd\n", strlen(&arr + 1)); //error,表示从整个数组末尾的下一个位置向后找'\0'//printf("%zd\n", strlen(&arr[0] + 1));//error,表示从数组首元素地址向后找'\0'return 0;
}

 对于每一个计算的解释都在对应的注释。

2.3、一维字符数组 (字符串的sizeof)

int main()
{char arr[] = "abcdef"; printf("%zd\n", sizeof(arr)); //7,表示计算整个数组的大小printf("%zd\n", sizeof(arr + 0));//8 ,表示计算首元素地址的大小printf("%zd\n", sizeof(*arr)); //1,表示计算'a'的大小printf("%zd\n", sizeof(arr[1]));//1,表示计算'b'的大小printf("%zd\n", sizeof(&arr)); //8,表示计算整个数组的地址大小printf("%zd\n", sizeof(&arr + 1));//8,表示计算整个数组的下一个位置地址的大小printf("%zd\n", sizeof(&arr[0] + 1));//8,表示计算第二个元素地址的大小return 0;
}

 对于每一个计算的解释都在对应的注释。

打印结果:

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

int main()
{char arr[] = "abcdef"; printf("%zd\n", strlen(arr)); //6,表示计算整个数组的长度printf("%zd\n", strlen(arr + 0));//6 ,表示计算数组从首元素地址开始的长度//printf("%zd\n", strlen(*arr)); //非法访问,表示解引用出首元素,即ASCII为97,0x00000061处,构成非法访问//printf("%zd\n", strlen(arr[1])); //非法访问,表示从第二个元素开始向后找,即ASCII为98,0x00000062处,构成非法访问printf("%zd\n", strlen(&arr)); //6,表示计算数组从整个数组的地址开始的长度//printf("%zd\n", strlen(&arr + 1)); //error,表示计算从整个数组下一个位置开始的长度printf("%zd\n", strlen(&arr[0] + 1));//5,表示计算数组从第二个元素地址开始的长度
}

 对于每一个计算的解释都在对应的注释。

打印结果:

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

int main()
{char* p = "abcdef"; //p是指针变量,指向第一个元素的地址printf("%zd\n", sizeof(p)); //8,表示计算指针变量所指向'a'地址的大小printf("%zd\n", sizeof(p + 1)); //8,表示计算指针变量所指向'b'地址的大小printf("%zd\n", sizeof(*p)); //1,表示计算指针变量所指向内容'a'(char)的大小printf("%zd\n", sizeof(p[0])); //1,表示计算指针变量所指向内容'a'(char)的大小printf("%zd\n", sizeof(&p)); //8,表示计算指向p指针的指针变量的大小(二级指针)printf("%zd\n", sizeof(&p + 1)); //8,表示计算指向p指针下一个位置的指针变量的大小(二级指针)printf("%zd\n", sizeof(&p[0] + 1));//8,表示计算指针变量所指向'b'地址的大小return 0;
}

 对于每一个计算的解释都在对应的注释。

打印结果:

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

int main()
{char* p = "abcdef"; printf("%zd\n", strlen(p)); //6,表示计算数组从'a'开始的长度printf("%zd\n", strlen(p + 1));//5 ,表示计算数组从'b'开始的长度//printf("%zd\n", strlen(*p)); //非法访问,表示解引用出首元素'a',即ASCII为97,0x00000061处,构成非法访问//printf("%zd\n", strlen(p[0])); //非法访问,表示解取出首元素'a',即ASCII为97,0x00000061处,构成非法访问//printf("%zd\n", strlen(&p)); //error,表示计算二级指针的长度//printf("%zd\n", strlen(&p + 1)); //error,表示计算二级指针下一个位置的长度printf("%zd\n", strlen(&p[0] + 1));//5,表示计算数组从'b'开始的长度return 0;
}

对于每一个计算的解释都在对应的注释。

打印结果:

2.7、 二维整型数组(sizeof)

int main()
{//sizeof(数组名)  这里的数组名指的是整个数组//&数组名         这里的数组名指的是整个数组,取出的是地址//其它情况均为数组首元素的地址int a[3][4] = { 0 }; printf("%zd\n", sizeof(a)); //48,计算的是整个数组的大小printf("%zd\n", sizeof(a[0][0]));//4,计算的是整个数组的第一个元素(int)的大小printf("%zd\n", sizeof(a[0])); //16,a[0]也是数组名(首行),计算的是整个第一行的大小printf("%zd\n", sizeof(a[0] + 1)); //8,这里a[0]并没有单独放在sizeof里面,代表第一行的第一个元素的地址,再+1,即&a[0][1]printf("%zd\n", sizeof(*(a[0] + 1))); //4,*&a[0][1],即计算a[0][1](int)的大小printf("%zd\n", sizeof(a + 1)); //8,这里a并没有单独放在sizeof里面,代表第一行的地址,再+1,即&a[1]printf("%zd\n", sizeof(*(a + 1))); //16,*&a[1],即计算a[1](int[4])的大小printf("%zd\n", sizeof(&a[0] + 1)); //8,&a[0]即取出第一行的地址,再+1,计算第二行的地址,&a[1]printf("%zd\n", sizeof(*(&a[0] + 1))); //16,*&a[1],即计算a[1](int[4])的大小printf("%zd\n", sizeof(*a)); //16,这里的a并没有单独放在sizeof内,a为&a[0],*a为a[0],计算整个a[0]的大小printf("%zd\n", sizeof(a[3]));//16,这里的a[3],即等价于a[0],a[1],a[2],并不造成越界的问题。计算的是类型int[4]return 0;
}

对于每一个计算的解释都在对应的注释。

打印结果:

 2.8、易混淆点

a[][]    int(单个元素)a[0]    int[4](第一行,4个int的数组)
a[0]     → int* (在表达式中退化为指针)a        int[3][4](整个二维数组)
a        → int(*)[4](在表达式中退化为指向行的指针)int* arr[]
int (*arr)[]

举个例子:

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

三、数组指针与指针数组

3.1、二者区别

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

int *ptr_arr[3];  // 3 个 int* 组成的数组
for (int i = 0; i < 3; i++) {ptr_arr[i] = malloc(4 * sizeof(int)); // 每行 4 个 int
}
ptr_arr[1][2] = 10; // 访问第 2 行的第 3 个元素

3.3、数组指针(静态二维数组)

int a[3][4] = {0};
int (*arr_ptr)[4] = a;  // 指向 a[0](第一行)
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])。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词