1. sizeof和strlen的对⽐
2. 数组和指针笔试题解析
一、sizeof(操作符)和strlen函数的对比
在我们初学习的时候,有许多同学会把sizeof和strlen函数给混淆,那么本章我们就来详细的探讨一下。
sizeof:是用来计算变量所占空间的大小的,单位是字节,如果操作数是类型的话,我们计算的是类型的大小。
我们举例子来说明
int main()
{
int num1 = 10;
double num2 = 5.0;
printf("%zd\n", sizeof(int));
printf("%zd\n", sizeof(num1));
printf("%zd\n", sizeof(10));
printf("%zd\n", sizeof(double));
printf("%zd\n", sizeof(num2));
printf("%zd\n", sizeof(5.0));
return 0;
}
1.2
strlen函数:求字符串的长度的,针对的是字符串(这个就是一个很大的区别)
strlen函数统计的是字符串\0之前的字符串,遇见\0停止。(如果字符中没有\0可能会造成越界访问)。
int main()
{
char arr1[10] = { 'a','b','c','d','e','f'};
char arr2[10] = "abcdef";
printf("%zd\n", sizeof(arr1)); //求得是字节的大小
printf("%zd\n", sizeof(arr2));
printf("%d\n", strlen(arr1)); //求的是字符串的长度
printf("%d\n", strlen(arr2)); //遇见\0为止
return 0;
}
printf(“%d\n”, strlen(arr1)); 打印出来的是6其实并不是,是随机值,因为我们是字符,字符没有\0,需要我们来添加,如果没有添加,就会自动在内存中找,直到遇见\0为止,所以是一个随机值。
1.3 sizeof和strlen函数的对比
我们来分析以下题目
注意:以下题目来自比特就业课(可能略有改动)
2.1一维数组
int main()
{
int a[] = { 1,2,3,4 };
printf("%zd\n", sizeof(a));//a是数组名,sizeof(a)计算的是整个数组的大小 16
printf("%zd\n", sizeof(a + 0)); //a + 0,数组名表示的数组首元素的地址 地址的大小是 4/8
printf("%zd\n", sizeof(*a)); //*a 是首元素 1 ,整形 4
printf("%zd\n", sizeof(a + 1)); // 表示的是 2的地址 4/8
printf("%zd\n", sizeof(a[1])); //表示的是 2 整形 4
printf("%zd\n", sizeof(&a)); //表示的是地址 4 /8
printf("%zd\n", sizeof(*&a)); //*&a==a表示的是整个数组 ,16
printf("%zd\n", sizeof(&a + 1)); //依旧是地址,只不过是跳过了该数组的地址,指向下一个 4 \8
printf("%zd\n", sizeof(&a[0])); //表示的是1的地址, 4 / 8
printf("%zd\n", sizeof(&a[0] + 1)); // 地址加1还是地址, 是地址就是4 / 8
return 0;
}
2.2 字符数组
int main()
{
char arr[] = { 'a','b','c','d','e','f' }; //字符数组,一个字符占一个字节
printf("%zd\n", sizeof(arr)); //sizeof(arr)是个特例,计算的是整个数组的大小。 6
printf("%zd\n", sizeof(arr + 0)); //arr + 0是地址 4 /8
printf("%zd\n", sizeof(*arr)); //拿出的是a,一个字符 1
printf("%zd\n", sizeof(arr[1])); //拿出的是一个字符b 1
printf("%zd\n", sizeof(&arr)); //取出的是整个数组的地址 ,是地址就是 4 /8
printf("%zd\n", sizeof(&arr + 1));//地址+1还是地址,4/8
printf("%zd\n", sizeof(&arr[0] + 1)); //找出的是b的地址 //4/8
return 0;
}
代码2:
int main()
{
//strlen函数计算的是字符串的长度,计算的\0之前的长度
char arr[] = { 'a','b','c','d','e','f' };//字符数组
printf("%zu\n", strlen(arr)); //没有\0,所以是个随机值。
printf("%zu\n", strlen(arr + 0));//依旧是个随机值
printf("%zu\n", strlen(*arr)); // 解引用得出的是'a',一个字符,不符合逻辑,无法打印
printf("%zu\n", strlen(arr[1]));//得出的是'b'
printf("%zu\n", strlen(&arr)); //地址 ,无法打印
printf("%zu\n", strlen(&arr + 1));//地址
printf("%zu\n", strlen(&arr[0] + 1));//地址
return 0;
}
代码3
int main()
{
//sizeof 计算的是数据字节的大小
char arr[] = "abcdef"; //字符数组,字符串(后边隐藏一个\0)
printf("%zd\n", sizeof(arr)); //特例计算的是整个数组的大小,7
printf("%zd\n", sizeof(arr + 0));// 地址 4 /8
printf("%zd\n", sizeof(*arr));//第一个字符a 1
printf("%zd\n", sizeof(arr[1]));//第二个字符b 1
printf("%zd\n", sizeof(&arr)); //地址 4/8
printf("%zd\n", sizeof(&arr + 1)); //地址 4 /8
printf("%zd\n", sizeof(&arr[0] + 1)); //地址 4 /8
return 0;
}
代码4:
int main()
{
// strlen 求的是字符串长度
char arr[] = "abcdef"; //字符数组
printf("%zd\n", strlen(arr)); //6
printf("%zd\n", strlen(arr + 0)); //6
printf("%d\n", strlen(*arr)); //取出的是一个a,报错 无法打印
printf("%d\n", strlen(arr[1]));//b,无法打印
printf("%d\n", strlen(&arr)); //地址 ,不符合 无法打印
printf("%d\n", strlen(&arr + 1)); //地址
printf("%d\n", strlen(&arr[0] + 1)); //地址
return 0;
}
代码5:
int main()
{
//sizeof 计算的是数据的大小,单位是字节
char* p = "abcdef"; //字符指针
printf("%zd\n", sizeof(p)); //p是地址,4/8
printf("%zd\n", sizeof(p + 1)); //依旧是指针 4/ 8
printf("%zd\n", sizeof(*p)); // 这个是字符 a 1
printf("%zd\n", sizeof(p[0])); //字符 1
printf("%zd\n", sizeof(&p));// 地址 4 /8
printf("%zd\n", sizeof(&p + 1));//地址 4 /8
printf("%zd\n", sizeof(&p[0] + 1)); //地址 指向的是b的地址 4/8
return 0;
}
代码 6 :
int main()
{
char* p = "abcdef"; //字符指针
printf("%zd\n", strlen(p));//p首元素的地址,strlen函数可以通过接收函数指针来访问 6
printf("%zd\n", strlen(p + 1)); //地址 从第二个元素的地址接收之后开始访问 5
printf("%zd\n", strlen(*p)); //a,报错
printf("%zd\n", strlen(p[0]));//a报错
printf("%zd\n", strlen(&p));//地址
printf("%zd\n", strlen(&p + 1)); //地址
printf("%zd\n", strlen(&p[0] + 1)); //地址
return 0;
}
2.3 二维数组
int main() //二维数组是由一维数组组成的数组名表示数组首元素的地址
{
int a[3][4] = { 0 };
printf("%zd\n", sizeof(a)); //a是数组名,sizeof(a)表示计算的是整个数组的大小 12 *4
printf("%zd\n", sizeof(a[0][0])); //拿出的是一个元素 0 4
printf("%zd\n", sizeof(a[0])); //拿出的是一维数组的名字 sizeof(arr)计算的是整个数组的大小 16
printf("%zd\n", sizeof(a[0] + 1)); //第二行的地址 4 /8
printf("%zd\n", sizeof(*(a[0] + 1))); //第二行第一个元素 4
printf("%zd\n", sizeof(a + 1)); //第二行的地址 4/8
printf("%zd\n", sizeof(*(a + 1))); //取出的是arr[1]该一维数组整个数组的大小 16
printf("%zd\n", sizeof(&a[0] + 1)); //地址 4/8
printf("%zd\n", sizeof(*(&a[0] + 1))); //取出的是arr[1]该一维数组整个数组的大小 16
printf("%zd\n", sizeof(*a)); //取出的是arr[0]该一维数组整个数组的大小 16
printf("%zd\n", sizeof(a[3])); //取出的是arr[3]该一维数组整个数组的大小 16
return 0;
}
这里我们总结一下:
1.sizeof(数组名),这里的数组名表示整个数组。计算的是整个数组的大小。
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3.除此之外的数组名都表示数组的首元素的地址。