[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()上的差别
相关文章推荐
- c语言:sizeof的使用,其不是函数,是一个操作符关键字,定义一个数组arr,输出arr和&arr的区别
- c语言:sizeof的使用,其不是函数,是一个操作符关键字,定义一个数组arr,输出arr和&arr的区别
- 参考C语言的qsort函数实现一个一个能对任意数据类型(包括结构体)的数组进行排序的函数(里面用的不是快速排序)
- C语言之数组专题:数组指针、指针数组、数组做函数参数退化、数组名、数组类型
- c语言之数组 sizeof strlen
- C语言学习5:数组定义,数组名的含义,数组作为函数参数,数组赋值,数组左右移动,最大最小,反向遍历,冒泡排序,sizeof 和strlen区别,gets和puts,strcpy,strcat,strcmp,strchr,strstr,strlen
- C语言中,当计算字符数组长度时,用sizeof 和strlen 的原理及两者的区别
- C语言中sizeof对数组和对指针操作的不同,以及sizeof中表达式赋值问题
- 解析sizeof, strlen, 指针以及数组作为函数参数的应用
- sizeof不是函数,C语言中sizeof的陷阱
- C语言中strlen()函数和sizeof()函数区别[关于字符串长度]
- sizeof()函数求类型所占字节大小-指针,数组
- c语言中的数组sizeof和strlen
- C语言strlen函数和sizeof操作符
- 如何求C语言字符串长度(strlen函数和sizeof关键字)
- c语言数组遇上sizeof和strlen
- C语言学习4: 函数返回值与传入参数,关于函数值传递和类型隐性转换,变量不同的作用域,static变量,多文件编译例如两个C文件,显示函数调用语句跳转,递归,斐波那契数列,多文件编译相同变量的问题。
- C语言数组类型以及函数类型的定义
- 一维数组,字符数组,字符串,二维数组在sizeof()和strlen()下的不同输出
- c语言重载不同类型数组的print(c99标准)