您的位置:首页 > 编程语言 > C语言/C++

[c语言]sizeof() 居然不是函数?!!strlen()和sizeof()纠缠在一起再碰到不同类型的数组,你还能分辨清吗?

2018-01-05 15:56 561 查看

sizeof()

我们在求一个数组的长度时,经常会用到这个”函数”,这看上去是一个求变量总字节的”函数”,其实别看它带着一个小括号,它和 int void const等一样是关键字.带上括号只是为了看上去更直观明了,而且有一个细节是括号里面的值不进行计算的,

例如

int a=3;

int b=2;

sizeof(a+b);

我们虽然知道sizeof在32位系统返回的是4.但是在不计算a+b括号怎么知道呢?我们要了解一个变量在内从空间中会开辟地址空间,然后在地址空间里存放数据.

sizeof在程序的编译期就已经确定,因为在编译期就可以确定变量开辟空间的大小,而空间里存放的数据要到运行期间才会确定.

a和b都是整型,所以在编译期间就会给a+b的结果开辟一片4字节大小的空间.

sizeof()和strlen()的练习

在开始之前要说明一点,当sizeof()括号中单独放数组名的时候,sizeof()求的是整个数组的字节大小.其他的情况出现数组名都表示指向首元素的指针.

Part 1

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//16  整个数组的字长
printf("%d\n",sizeof(a+0));//4  第一个元素地址的字长
printf("%d\n",sizeof(*a)); //4 *a==*(a+0)==a[0] 第一个元素的字长
printf("%d\n",sizeof(a+1));//4  第二个元素的地址
printf("%d\n",sizeof(a[1]));//4  第二个元素地址字长
printf("%d\n",sizeof(&a));  //4    整个数组地址的字长(地址是4个字长)
printf("%d\n",sizeof(*&a)); //16   &a取整个数组地址的地址 然后*(&a)等于*p 表示里面所存的值, 所以是里面值的字长16
printf("%d\n",sizeof(&a+1));//4 跳过此数组后的地址的字长
printf("%d\n",sizeof(&a[0]));//4 第1个元素的地址字长
printf("%d\n",sizeof(&a[0]+1));//4 第二个元素的地址字长


通过上面的练习,我们可以总结到:

数组名广义上是一个指向首元素的指针

但在sizeof()中单独出现就代表所有的元素(注意这里就不代表指针了)

a[0]就等于 *a(把指针解引用)

&a[0]就等于a(指针指向a[0]的地址)

Part 2

char arr[] = {'a','b','c','d','e','f'};

printf("%d\n", strlen(arr));//随机值   首元素地址往后数数组有\0才表示结束 这里不知道在哪结束

printf("%d\n", strlen(arr+0));//随机值

printf("%d\n", strlen(*arr));//err    strlen(这里面传的是地址呀)

// *arr解引用后是一个值"a"的ASII(98) 98这个地址你是不能随便访问的

printf("%d\n", strlen(arr[1]));//err   同上不过换成b的ASII码

printf("%d\n", strlen(&arr));//随机值    这里是整个数组的地址,不过也是首个元素的地址

printf("%d\n", strlen(&arr+1));//随机值   从整个数组地址+1后的地址开始往后数

printf("%d\n", strlen(&arr[0]+1));       //随机值从第二个元素的地址开始往后数

printf("%d\n", sizeof(arr));//6       一个 char 1个字节  sizof(单独的数组名表示整个数组长度)

printf("%d\n", sizeof(arr+0));//4     a首元素的地址 4个字节

printf("%d\n", sizeof(*arr));//1       解引用 表示第一个元素'a' 长度是1

printf("%d\n", sizeof(arr[1]));//1      同上 不过是'b'

printf("%d\n", sizeof(&arr));//4         整个数组的地址 ,地址长度4个字节

printf("%d\n", sizeof(&arr+1));//4           整个数组的地址后面一个地址的 地址长度

printf("%d\n", sizeof(&arr[0]+1));//4       第二个元素地址的长度


通过上面练习,我们又可以发现

strlen函数传参的参数是一个char*,也就是字符类型的指针

strlen计算结束标志是表示是碰见’\0’(‘\0’不计入总长度)

地址变量占4个字节空间

Part 3

char arr[] = "abcdef";

printf("%d\n", strlen(arr));//6     //字符串默认后面有\0   表示首元素地址往后数

printf("%d\n", strlen(arr+0));//6     和上面一样  注意strlen 和size of的区别!!!

printf("%d\n", strlen(*arr));//err     错  不可能访问的内存地址

printf("%d\n", strlen(arr[1]));//err   错  同上

printf("%d\n", strlen(&arr));//6          整个元素的地址     其实也是第一个元素的地址 数到\0 刚好6个

printf("%d\n", strlen(&arr+1));//随机值   跳出数组地址了(也跳出了\0)

printf("%d\n", strlen(&arr[0]+1));//5   从第二个元素地址开始数 数到\0 5个

printf("%d\n", sizeof(arr));//7          全部字长字符串默认包含 \0

printf("%d\n", sizeof(arr+0));//4      首地址

printf("%d\n", sizeof(*arr));//1       'a'

printf("%d\n", sizeof(arr[1]));//1   ' b'

printf("%d\n", sizeof(&arr));//4       整个数组的地址 的地址字长

printf("%d\n", sizeof(&arr+1));//4     整个数组的地址下一个地址 的地址字长

printf("%d\n", sizeof(&arr[0]+1));//4    'b'的地址 的字长  4个


通过以上的练习,我们可以发现

如果把数组定义为 char a[]=”abcd” 数组已经包换’\0’了

数组的长度就是5(包换’\0’),用sizeof(a)/sizeof(a[0])求得

但用strlen求得字符串长度为4

Part 4

char *p = "abcdef";

printf("%d\n", sizeof(p));//4
//    p是个指针,和地址字长一样是4个字节  区分sizeof(p) 和 sizeof(arr) 注意这个不是一个数组!!!! p指向第一个元素的首地址

printf("%d\n", sizeof(p+1));//4       同上 是第二个元素的地址

printf("%d\n", sizeof(*p));//1       解引用 不解释

printf("%d\n", sizeof(p[0]));//1     第一个元素字长

printf("%d\n", sizeof(&p));//4      地址的地址永远是4个字长  注意p里存的"值"是"一片地址" p里能存"值",那P也得有地址 &p就是p地址

printf("%d\n", sizeof(&p+1));//4   地址的地址+1还是4个字长

printf("%d\n", sizeof(&p[0]+1));//4   地址的地址+1还是4个字长

printf("%d\n", strlen(p));     // 6

printf("%d\n", strlen(p+1));   //  5

printf("%d\n", strlen(*p));    //  非法

printf("%d\n", strlen(p[0]));  //  非法

printf("%d\n", strlen(&p));   //   从地址的地址开始数 随机值

printf("%d\n", strlen(&p+1));//     同上 随机值??

printf("%d\n", strlen(&p[0]+1));//同上 随机值??


通过以上练习发现 char *p和char *arr 大体上是相似的,不同的是

sizeof(p) 此时p是指针,不是数组名,所以没有数组名单独出现在sizeof里面的特性

Part 4

int a[3][4] = {0};

/*printf("%p\n", &a[0][0]);
printf("%p\n", a[0]+1);*/

printf("%d\n",sizeof(a));//48   easy

printf("%d\n",sizeof(a[0][0]));//4     第零个元素字长

printf("%d\n",sizeof(a[0]));//16

//第1个数组元素字长  这里 a[0]表示二维数组的第一个元素  sizof(数组名) 总长

printf("%d\n",sizeof(a[0]+1));//4      这里是第一行第二个元素的字长

printf("%d\n",sizeof(a+1));//4  //第二个元素的字长

//   第二行的整个数组的地址 二维数组中 a表示首数组的地址

printf("%d\n",sizeof(&a[0]+1));//4      第二行的整个数组的地址 (第一行数组取地址加+)

printf("%d\n",sizeof(*a));//   16       二维数组的首地址是第一行数组的地址  *a表示对第一行进行解引用

printf("%d\n",sizeof(a[3]));//16        sizeof内部不进行运算,也就是不判断合法性.但知道其分配的地址空间大小


通过对第四部分练习可以发现二维数组中的元素类型是一维数组.

具体详解请见本人另一篇博客

原来二维数组内部隐藏着这样不为人知的秘密……

总结

sizeof()是求的类型所占字节大小,所以很多关于地址和指针求字节大小,都是占4个字节,但是要明白是谁的地址.

strlen函数的声明是 char* strlen(const char*str) 注意传进的形参类型是字符指针char *类型

区分char *p = “abcdef”char arr[] = “abcdef”在sizeof()和strlen()上的差别
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐