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

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()上的差别
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值