sizeof 和 strlen主要区别如下:
1、sizeof是运算符,strlen是C语言标准库函数。
2、 strlen 测量的是字符串的实际长度,以’\0’ 结束,返回结果不包括’\0’ 。
3、而sizeof 测量的是字符的分配大小,它的参数可以是数组、指针、类型、对象、函数等。
题目1:
int main()
{
char arr[20] = "abcdef";
size_t len = strlen(arr);//6
//统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数
printf("len = %zd\n", len);
size_t sz = sizeof(arr);//20
printf("sz = %zd\n", sz);char arr[] = { 'a','b','c'};//42,随机的,编译器随机
\0的位置不确定,终的数值也不确定
printf("%zd\n", strlen(arr));
char arr[6] = "abcdef";//err \0 有7个字符,越界
return 0;
}
题目2:
int main()
{
int a[] = { 1,2,3,4 };//a数组有四个元素,每个元素是int类型的数据printf("%d\n", sizeof(a));//16 - sizeof(数组名)的情况,计算整个数组的大小,单位是字节 - 4 * 4 = 16
printf("%d\n", sizeof(a + 0));//4 or 8 取决于是32位还是64位
//a表示的是数组首元素的地址,a+0还是首元素的地址
printf("%d\n", sizeof(*a));//4 a表示的是数组首元素的地址,*a就是首元素,大小是4个字节
printf("%d\n", sizeof(a + 1));//4 or 8
//a + 1是第二个元素的地址
printf("%d\n", sizeof(a[1]));//4 a[1]是数组的第二个元素,大小是4个字节
printf("%d\n", sizeof(&a));//4 or 8 &a - 取出的是数组的地址,但是数组的地址也是地址,
//int (*pa)[4] = &a
//int (*)[4]
printf("%d\n", sizeof(*&a));//16
//1.抵消 &* sizeof(*&a) == sizeof(a)
//2.&a 的类型是数组指针,int(*)[4],*&a就是对数字指针解引用访问一个数组的大小,是16个字节printf("%d\n", sizeof(&a + 1));//4 or 8 &a+1是跳过整个数组后的地址,是地址,大小就是4/8个字符
printf("%d\n", sizeof(&a[0])); //4 or 8 &a[0]是第一个元素的地址,大小就是4/8个字符
printf("%d\n", sizeof(&a[0] + 1));//4 or 8
//&a[0]+1是第二个元素的地址,大小就是4/8个字符return 0;
}
题目3:
int main()
{
char arr[] = { 'a','b','c','d','e','f' };//arr数组中有6个元素printf("%d\n", sizeof(arr));//6 计算的是整个数组的大小
printf("%d\n", sizeof(arr + 0));//4 or 8 arr+0是数组的第一个元素的地址
printf("%d\n", sizeof(*arr));//1 *arr是首元素地址的解引用,就是1个字节
printf("%d\n", sizeof(arr[1]));//1 - arr[1] = 'b'
printf("%d\n", sizeof(&arr));//4 or 8
printf("%d\n", sizeof(&arr + 1));//4 or 8
printf("%d\n", sizeof(&arr[0] + 1));//4 or 8return 0;
}
题目4:
int main()
{
char arr[] = "abcdef";
printf("%zd\n", sizeof(arr));
//sizeof的返回值是size_t,是无符号型,应该用%zd接收printf("%zd\n", sizeof(arr + 0));//arr+0是数组首元素的地址,地址大小是4、8个字节
printf("%zd\n", sizeof(*arr));//*arr是数组首元素,这里计算的是首元素的大小 1
printf("%zd\n", sizeof(arr[1]));//1
printf("%zd\n", sizeof(&arr));//&arr - 是数组的地址,数组的地址也是地址 4/8
printf("%zd\n", sizeof(&arr + 1));&arr+1,跳过整个数组,指向了数组的后边 4/8
printf("%zd\n", sizeof(&arr[0] + 1));//&arr[0]+1是第二个元素的地址 4/8return 0;
}
此时&arr+1跳过整个数组
题目5:
int main()
{
char arr[] = "abcdef";printf("%zd\n", strlen(arr));//arr是数组首元素的地址 6
printf("%zd\n", strlen(arr + 0));//arr + 0 是数组首元素的地址 6
printf("%zd\n", strlen(*arr));// 传递的是'a' - 97 //err
printf("%zd\n", strlen(arr[1]));// 'b' - 98 //err
printf("%zd\n", strlen(&arr));//6 ,&arr虽然是数组的地址,但是也是指向数组arr的起始位置
printf("%zd\n", strlen(&arr + 1));//随机值
printf("%zd\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 - 5
return 0;
}
这里如果要传参,则用char *p来接收&arr,接收后的类型为char (*)[7],但strlen所需要的形参类型为char *str,编译会警告,但仍然能传递
(补充:因为strlen函数要求传入一个指向字符的指针,而不是一个指向字符数组的指针。而char (*p)[7]是一个指向字符数组的指针,所以当它传入strlen函数时会出现警告。)
题目6:
int main()
{
char* p = "abcdef";
printf("%d\n", sizeof(p));//4/8 计算的指针变量的大小
printf("%d\n", sizeof(p + 1));//p + 1是'b'的地址,是地址大小就是4/8个字节
printf("%d\n", sizeof(*p));//*p就是'a',大小是1个字节
printf("%d\n", sizeof(p[0]));//p[0]-->*(p+0) - *p//1个字节
printf("%d\n", sizeof(&p));//&p也是地址,是指针变量p的地址大小是4/8字节
printf("%d\n", sizeof(&p + 1));//&p+1是指向p指针变量后面的空间,也是地址 - 4/8
printf("%d\n", sizeof(&p[0] + 1));//&p[0]+1是'b'的地址 - 4/8
return 0;
}
int main()
{
char* p = "abcdef";
printf("%zd\n", strlen(p)); //6
printf("%zd\n", strlen(p + 1));//5
printf("%zd\n", strlen(*p));//'a'-97 err
printf("%zd\n", strlen(p[0]));//p[0]--*(p+0)-->*p //err
printf("%zd\n", strlen(&p));//随机值 不确定\0的位置
printf("%zd\n", strlen(&p + 1));//同上
printf("%zd\n", strlen(&p[0] + 1));//从b的地址往后数 - 5return 0;
}
二维数组题(重点):
int main()
{
//二维数组也是数组,之前对数组名的理解也同样适用
int a[3][4] = { 0 };
printf("%zd\n", sizeof(a));//12*4 = 48个字节,数组名单独放在sizeof内部
printf("%zd\n", sizeof(a[0][0]));//4
printf("%zd\n", sizeof(a[0]));//a[0]是第一行这个一维数组的数组名,数组名单独放在了sizeof内部了
//计算的是第一行的大小,单位是字节,16个字节printf("%zd\n", sizeof(a[0] + 1));
//a[0]是第一行这个一维数组的数组名,这里表示首元素地址
//也就是a[0][0]的地址,a[0]+1是a[0][1]的地址printf("%zd\n", sizeof(*(a[0] + 1)));//a[0][1] - 4个字节
printf("%zd\n", sizeof(a + 1));//a是二维数组的数组名,但是没有&,也没有单独放在sizeof内部
//所以这里的a是数组首元素的地址,应该是第一行的地址,a+1是第二行的地址
//大小也是4/8个字节
printf("%zd\n", sizeof(*(a + 1)));//*(a+1)==>a[1] - 第二行的数组名,单独放在sizeof内部,计算的是第二行的大小 - 16个字节
printf("%zd\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址,&a[0]+1就是第二行的地址 4/8
printf("%zd\n", sizeof(*(&a[0] + 1)));
//访问第二行,计算的是第二行的大小,16个字节
//int(*p)[4] = &a[0]+1printf("%zd\n", sizeof(*a));
//这里的a是第一行的地址,*a就是第一行,sizeof(*a)计算的是第一行的大小 - 16
//*a -->*(a+0)-->a[0]
printf("%zd\n", sizeof(a[3]));//这里不存在越界
//sizeof内部的表达式不会真实计算的
//计算的是第四行的大小 - 16return 0;
}
上述题目总结: