前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >详解sizeof()和strlen()的细节及用法

详解sizeof()和strlen()的细节及用法

作者头像
用户11029269
发布2024-03-19 17:47:08
1060
发布2024-03-19 17:47:08
举报

sizeof和strlen的对比

  1. sizeof() 计算变量所占内存内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。 sizeof ()只关注占⽤内存空间的大小,不在乎内存中存放什么数据。
  2. strlen()是C语言库函数,功能是求字符串长度。 函数原型:
代码语言:javascript
复制
  size_t strlen ( const char * str );

统计的是从 strlen()函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数。strlen()函数会⼀直向后找\0 字符,直到找到为止,所以可能存在越界查找。 那我们思考一下如果我们传一个字符给strlen()会怎么样?详细请看下面求strlen(*arr),这时我们会讲到实际案例!!! 那我们再思考一下如果我们传一个数组地址给strlen()会怎么样?详细请看下面求strlen(&arr),这时我们会讲到实际案例!!!

在开始下面的介绍前还有一点非常重要,数组名的意义: 3. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。 4. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。 5. 除此之外所有的数组名都表示首元素的地址。

计算一维数组

整形数组

代码语言:javascript
复制
    int a[] = {1,2,3,4};
    printf("%d\n",sizeof(a));
    printf("%d\n",sizeof(a+0));
    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));
    printf("%d\n",sizeof(&a[0]));
    printf("%d\n",sizeof(&a[0]+1));

我们先看一下输出的结果:

1.sizeof(a);//sizeof(数组名) 计算的是数组的总大小-=单位字节–16 2.sizeof(a+0);//肯定有人想问上一个还是16字节,怎么这儿就变成8了?其实这里a+0是一个表达式,并不满足sizeof(数组名)形式,所以这里a还是首元素地址,a+0还为首元素地址,地址大小都为4 / 8字节 3.sizeof(*a);//这里a是首元素地址,所以*a就是首元素的类型(int)的大小,即为4 4.sizeof(a+1);//这里a为首元素地址,则a+1就是第二个元素地址,类比于2.,为4 / 8字节 5.sizeof(a[1]);//第二个元素大小,4 6.sizeof(&a);//&a取出的是数组的地址,是地址都是4 / 8 7.sizeof(*&a);//&a是数组a的地址,*解引用后则就是数组a,此处计算的还是数组的大小,16字节 8…sizeof(&a+1);//根据上面我们不难想到,此处&a+1相当于&a跳过了一个数组,但还是一个地址,为4 / 8字节 9…sizeof(&a[0]);//首元素地址,4 / 8字节 10…sizeof(&a[0]+1);//第二个元素的地址,4 / 8字节

字符数组

字符数组与整形数组的sizeof()用法极其相似,这里就不多介绍了!

代码语言:javascript
复制
    char arr[] = { 'a','b','c','d','e','f' };
    printf("%d\n", strlen(arr));
    printf("%d\n", strlen(arr+0));
    printf("%d\n", strlen(*arr));
    printf("%d\n", strlen(arr[1]));
    printf("%d\n", strlen(&arr));
    printf("%d\n", strlen(&arr+1));
    printf("%d\n", strlen(&arr[0]+1));

运行结果:

1.strlen(arr); 2.strlen(arr+0);

我们可以看出这个字符数组并没有以'\0'结尾,所以strlen()计算首元素地址时,就产生了随机值!所以第一个和第二个是随机值! 3.strlen(*arr); 4. strlen(arr[1]); 开头我们介绍了strlen()函数接收的是一个地址。此处的*arr是数组首元素,arr[1]是数组第二个元素。所以编译器就会报错。还可以再深入讲一下,既然strlen()接收的是一个地址,而*arr是字符a,ASCII表的值为97,,此时strlen()就会把97当成一个地址去访问空间,但这个地址不是我们所拥有的空间,就形成了非法访问。

这里0x0000000000000061其实就是97,这也就印证了我们的说法。 5.strlen(&arr); 6.strlen(&arr+1); 7.strlen(&arr[0]+1); &arr,&arr+1,&arr[0]+1其实都是地址,虽然第一个是一个数组的地址,但他的地址与首元素地址一样,所以为随机值,第二个跳过了一个数组所以为随机值-6,6是数组大小,第三个以为跳过了数组中的一个元素,所以为随机值-1。 可以看出虽然&arr是一个数组地址,类型为数组指针char(*p)[6],事实上这只是当成一个地址看待,并不会真正影响结果。

字符串

代码语言:javascript
复制
    char arr[]="abcdef";
    printf("%d\n", strlen(arr));
    printf("%d\n", strlen(arr+0));
    printf("%d\n", strlen(&arr));
    printf("%d\n", strlen(&arr+1));
    printf("%d\n", strlen(&arr[0]+1));

我们看到这其实就会想到这不就是char arr[] = { 'a','b','c','d','e','f' ,'\0'};吗?没错!这里sizeof()计算方法还是与上面是一样的,但strlen()还是要说一下的。 1.strlen(arr); 2.strlen(arr+0); 既然有了'\0'为结尾,那结果肯定就是字符串长度了,即为6 3.strlen(&arr);//这就会返回'\0'之前字符个数,即为6 4.strlen(&arr+1);//但是这里&arr+1跳过了数组arr,于是返回了一个随机值 5.strlen(&arr[0]+1);//这指向的是'b'的地址,于是返回5

计算常量字符串

代码语言:javascript
复制
    char *p = "abcdef";
    printf("%d\n", sizeof(p));
    printf("%d\n", sizeof(p+1));
    printf("%d\n", sizeof(*p));
    printf("%d\n", sizeof(p[0]));
    printf("%d\n", sizeof(&p));

这儿难道是把"abcdef"放到p里面?其实这里的p仅仅放了'a'的地址 1.sizeof(p);//这儿就是计算指针变量p的地址,4 / 8字节 2.sizeof(p+1);//p+1得到的是字符'b'的地址,4 / 8字节 3.sizeof(*p);//*p其实就是字符串的第一个字符'a',1字节 4.sizeof(p[0]);//事实上这里的p[0]就等价于*(p+0),就是第一个元素,1字节 5.sizeof(&p);//这里&p把指针p的地址取出来了,4 / 8字节

代码语言:javascript
复制
    char *p = "abcdef";
    printf("%d\n", strlen(p));
    printf("%d\n", strlen(&p));
    printf("%d\n", strlen(&p+1));

1.strlen(p); //上面也分析过了,p存放的就是'a'的地址,strlen()找到'\0'结束,所以就是6了 2.strlen(&p); 3.strlen(&p+1);//&p是指针p的地址,这里我画了一张图来说明一下:

所以这里求出来的其实是随机值!

计算二维数组

代码语言:javascript
复制
    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));
    printf("%d\n",sizeof(*(a+1)));
    printf("%d\n",sizeof(&a[0]+1));
    printf("%d\n",sizeof(*(&a[0]+1)));
    printf("%d\n",sizeof(*a));
    printf("%d\n",sizeof(a[3]));

我们看看编译器输出的结果吧!!!下面讲解一下为什么。

1.sizeof(a);//这里的a代表整个二维数组的数组名,大小为124,36字节 2.sizeof(a[0][0]);//这则是数组第一个元素,4字节 3.sizeof(a[0]);//a[0]是二维数组的第一行作为一维数组的数组名,所以sizeof()所求的是数组第一行的大小,大小为44,16字节 4.sizeof(a[0]+1);//此处a[0]表示第一行的数组名,表示的是首元素地址,其实就是第一行第一个元素的地址,所以a[0]+1就表示第一行第二个元素的地址,4 / 8字节 5.sizeof(*(a[0]+1));//如上*a[0]+1就是第一行第二个元素,4字节 6.sizeof(a+1);//我们考虑一下这是谁的地址呢?a是二维数组的数组名,是首元素地址,而二维数组的首元素是他的第一行,那么a就是第一行的地址,那么加一后就是第二行的地址,4 / 8字节

从这我们也可以看出两个地址相差了16,正是4个整形的大小,所以这也验证了上面,加一后跳过了一行。

7.sizeof(*(a+1));//如6.,解引用后就代表第二行,16字节 8.sizeof(&a[0]+1);//&a[0]取出第一行地址,加一后为第二行地址,4 / 8字节 9.sizeof(*(&a[0]+1));//解引用得到数组第二行,16字节 10.sizeof(*a);//a是首元素地址,第一行地址,解引用后为第一行,16字节 11.sizeof(a[3]);//a[3]是数组第四行,虽没有第四行,但根据数组类型,计算的任是一行有四个整形的数组大小,所以还为16

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • sizeof和strlen的对比
  • 计算一维数组
    • 整形数组
      • 字符数组
        • 字符串
        • 计算常量字符串
        • 计算二维数组
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档