在 操作符详解中,我们介绍到了sizeof操作符的作用,下面通过一些习题来进一步区分sizeof和strlen以及指针和数组在strlen和sizeof中的大小计算。(博主编译器为32位平台)
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a+0));//(取决于平台) - 1的地址
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a+1));//跳过一个整型后的地址
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));//地址
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));//跳过1个数组后的地址
printf("%d\n", sizeof(&a[0]));//地址
printf("%d\n", sizeof(&a[0]+1));//地址
return 0;
}
答案为:
重点剖析:
-
&a取出的是整个数组的地址,再解引用得出的是整个数组的大小。因此为16个字节。 -
a+1和&a + 1的区别:
(a + 1)相当于a + 1 * sizeof(int)
(&a + 1)相当于&a + 1 * sizeof(a)
💬 a代表数组首元素的地址
💬&a代表整个数组的地址
这也是它们加一造成的差异原因之一
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//字符数组长度
printf("%d\n", sizeof(arr+0));//数组首元素地址
printf("%d\n", sizeof(*arr));//第一个元素的大小
printf("%d\n", sizeof(arr[1]));//第二个元素大小
printf("%d\n", sizeof(&arr));//取出数组地址 - 首元素地址
printf("%d\n", sizeof(&arr+1));//地址(跳过一整个字符数组后指向的地址)
printf("%d\n", sizeof(&arr[0]+1));//第二个元素的地址
return 0;
}
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
//printf("%d\n", strlen(*arr));//error
//printf("%d\n", strlen(arr[1]));//error
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
return 0;
}
strlen遇到\0才停止。
除下面两个表达式,其余结果均为随机值。
❓为什么呢?
因为strlen函数接收的是指针,而*arr和arr[1]均为某一字符,传过去的是ASCII码值。会导致程序错误。
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//计算长度(包括\0)
printf("%d\n", sizeof(arr + 0));//地址
printf("%d\n", sizeof(*arr));//对首元素地址解引用
printf("%d\n", sizeof(arr[1]));//第二个元素大小
printf("%d\n", sizeof(&arr));//地址
printf("%d\n", sizeof(&arr + 1));//地址
printf("%d\n", sizeof(&arr[0] + 1));//地址
return 0;
}
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//计算长度(不包括\0)
printf("%d\n", strlen(arr + 0));//计算从第一个字符后字符串的长度
//printf("%d\n", strlen(*arr));//error
//printf("%d\n", strlen(arr[1]));//error
printf("%d\n", strlen(&arr));//取出数组地址 - 还是看作从首元素地址开始计算
printf("%d\n", strlen(&arr + 1));//跳过一个数组后寻找\0 - 获得随机值
printf("%d\n", strlen(&arr[0] + 1));//跳过第一个字符后开始计算长度
return 0;
}
此表达式结果为随机值。
int main()
{
char* p = "abcdef";
printf("%d\n", sizeof(p));//获得指针大小
printf("%d\n", sizeof(p + 0));//地址
printf("%d\n", sizeof(*p));//p指向首元素地址,解引用为1
printf("%d\n", sizeof(p[1]));//第二个元素大小
printf("%d\n", sizeof(&p));//地址
printf("%d\n", sizeof(&p + 1));//地址
printf("%d\n", sizeof(&p[0] + 1));//地址
return 0;
}
p为指针,内存中存放a的地址,指向字符串的首个字符。计算p的长度即为计算地址的大小
int main()
{
char* p = "abcdef";
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 0));//5
//printf("%d\n", strlen(*p));//error
//printf("%d\n", strlen(p[1]));//error
printf("%d\n", strlen(&p));//随机值
printf("%d\n", strlen(&p + 1));//随机值
printf("%d\n", strlen(&p[0] + 1));//5
return 0;
}
&p:p在内存中放的值完全不知道,所以为随机值
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//代表整个二维数组大小
printf("%d\n", sizeof(a[0][0]));//代表第一行第一个元素
printf("%d\n", sizeof(a[0]));//代表第一行元素总大小
printf("%d\n", sizeof(a[0]+1));//代表第一行第一个元素的地址跳过一个整型后的地址
printf("%d\n", sizeof(*(a[0]+1)));//代表第一行第二个元素解引用后的类型大小
printf("%d\n", sizeof(a+1));//代表首元素地址(即第一行地址) + 1 - 即第二行地址
printf("%d\n", sizeof(*(a + 1)));//代表*(a+1) <=> a[1],第二行元素总大小
printf("%d\n", sizeof(&a[0]+1));//&a[0]代表取出第一行的地址,+1代表取出第二行的地址
printf("%d\n", sizeof(*(&a[0] + 1)));//解引用,计算的是第二行
printf("%d\n", sizeof(*a));//代表对第一行地址解引用,计算的是第一行元素总大小
printf("%d\n", sizeof(a[3]));
return 0;
}
重点剖析:
a[0]能代表第一行的数组名
乍一看,我们会觉得这种形式数组越界了,其实不然!要知道,sizeof( )里面的表达式不作实际的运算。因此,无论a[ ]里面是什么都不会影响计算
上面所有的题目,你做对了多少题呢?如果你全都做对了,那么恭喜你!如果有一些题目做错了,不必焦躁,勤练,你一定会成功的!