sizeof 和 strlen的对比及相关例题精讲与解析

您所在的位置:网站首页 佳能g7x2和200d的内存卡是一样的吗 sizeof 和 strlen的对比及相关例题精讲与解析

sizeof 和 strlen的对比及相关例题精讲与解析

2023-09-10 08:07| 来源: 网络整理| 查看: 265

sizeof 和 strlen的对比 sizeofstrlen sizeof是操作符strlen是库函数,使用需要包含头文件 string.h   sizeof计算操作数所占内存的大小,单位是字节 srtlen是求字符串长度的,统计的是 \0 之前字符的个数 不关注内存中存放什么数 据 关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可能会越界

sizeof和strlen的返回值类型是 size_t,它的本质是无符号整形,输出是%zd

还可以用 %u(无符号十进制整数),%ud(unsigned int),%ld(long int),%lld(long long int)

%lu(unsigned long int),%llu(unsigned long long int) 输出,不然会有警告。

 从上文的代码,我们还可以得出一个结论。

sizeof 在计算大小的时候,其实是根据类型推算的。 sizeof的操作数如果是一个表达式,表达式的不参与计算的。

例题精讲 一维数组

sizeof(a)16字节sizeof(a)中的a代表整个数组的元素,所以计算出整个数组的大小sizeof(a + 0)4/8字节数组名a并没有单独放在sizeof内部,所以a就是数组首元素的地址sizeof(*a)4字节

a就是数组首元素的地址,*a==*&a[0]==a[0]

sizeof(a+1)4/8字节a+1==&a[0]+1==&a[1]sizeof(a[1])4字节计算第2个元素的大小sizeof(&a)4/8字节&a代表整个数组的地址,在一维数组中也等同于行地址sizeof(*&a)16字节

*&a==a==&a[0],由于转化为a时,恰巧在sizeof中,sizeof(a)中的a为整个数组的元素

sizeof(&a+1)4/8字节&a+1是跳过整个数组后的地址,是地址大小就是4/8个字节sizeof(&a[0])4/8字节首元素的地址sizeof(&a[0]+1)4/8字节第二个元素的地址 字符数组 例一

sizeof(arr)6字节这里的arr代表整个数组的元素sizeof(arr + 0)4/8字节这里的arr是数组首元素的地址,arr+0 还是首元素的地址sizeof(*arr)1字节*arr==*&arr[0]==arr[0]sizeof(arr[1])1字节arr[1]就是数组的第二个元素sizeof(&arr)4/8字节&arr整个数组的地址,在一维数组中也等同于行地址sizeof(&arr + 1)4/8字节&arr+1 是跳过整个数组后的地址,是地址大小就是4/8个字节sizeof(&arr[0] + 1)4/8字节&a[0]+1==&a[1],第二个元素的地址 例二 strlen(arr)随机值数组中没有明确给出\0,会一直在内存中往下找\0strlen(arr + 0)随机值arr+0==arr==&arr[0],理由同上strlen(*arr)err*arr==arr[0]=='a'-->97,把97当成地址非法访问--errstrlen(arr[1])errarr[1]==‘b’-->98,把98当成地址非法访问--errstrlen(&arr)随机值&arr是整个数组的地址但大小和数组首元素地址&a[0]相同,这里会从&a[0]地址处往下找\0strlen(&arr + 1)随机值&arr+1跨越了整个数组的地址,从整个数组后一个地址找\0strlen(&arr[0] + 1)随机值&arr[0]+1==&arr[1],从第二个元素的地址开始找\0 例三

sizeof(arr)7字节整个数组的大小sizeof(arr + 0)4/8字节arr==&arr[0],arr + 0 还是首元素的地址sizeof(*arr)1字节arr表示数组首元素的地址,*arr就是首元素sizeof(arr[1])1字节arr[1]是第二个元素sizeof(&arr)4/8字节&arr是整个数组的地址,在一维数组中也等同于行地址sizeof(&arr + 1)4/8字节&arr是数组的地址,&arr+1就是跳过整个数组的那个地址sizeof(&arr[0] + 1)4/8字节&arr[0]+1==&arr[1],第二个元素的地址 例四

strlen(arr)6arr是首元素的地址strlen(arr + 0)6arr+1 也是首元素的地址strlen(*arr)err*arr==arr[0] 非法访问strlen(arr[1])err非法访问strlen(&arr)6&arr是整个数组的地址但大小和数组首元素地址&a[0]相同,这里会从&a[0]地址处往下找\0strlen(&arr + 1)随机值跳过整个数组后的地址,从这里开始向后找\0strlen(&arr[0] + 1)5&arr[0] + 1==&arr[1],从第二个元素的地址往后找\0 例五 sizeof(p)4/8字节p指向‘a’的地址sizeof(p + 1)4/8字节p+1是‘b’的地址sizeof(*p)1字节*p 是首字符‘a'sizeof(p[0])1字节p[0]==*(p+0)==asizeof(&p)4/8字节&p是p的地址sizeof(&p + 1)4/8字节&p + 1也是地址,&p+1是跳过p变量后的地址sizeof(&p[0] + 1)4/8字节&p[0]+1==&*(p+0)+1=='b'的地址 例六 strlen(p)6p中存放的是a的地址,从a的地址开始向后访问strlen(p + 1)5p+1=='b'的地址,从b的地址开始向后访问strlen(*p)err*p=='a' 非法访问   strlen(p[0])errp[0]==*(p+0)==*p=='a'  非法访问strlen(&p)随机值&p是p的地址,从p所占空间的起始位置开始查找的strlen(&p + 1)随机值从p所占空间的起始位置的下一位开始查找的strlen(&p[0] + 1)5&p[0]+1==&*(p+0)+1==p+1=='b'的地址 ⼆维数组

sizeof(a)48字节计算的是整个二维数组的大小sizeof(a[0][0])4字节a[0][0]是第一行第一个元素sizeof(a[0])16字节

a[0]其实就是第一行的数组名,计算的是第一行的大小,a[0]==&a[0][0],但这里作为收缩的数组名,单独在sizeof中表示这一行数组的所有元素

sizeof(a[0]+1)4/8字节a[0]+1==&a[0][0]+1==&a[0][1]sizeof(*(a[0]+1))4字节*(a[0]+1)==a[0][1]sizeof(a+1)4/8字节a+1==&a[0]+1==&a[1],就是第二行的地址sizeof(*(a+1))16字节

*(a+1)==*(&a[0]+1)==*&a[1]==a[1],转换到这里,就不能再转换了

这里恰巧构成sizeof(a[1]),a[1]单独在sizeof中表示这一行所有元素

sizeof(&a[0]+1)4/8字节&a[0]+1==&a[1]sizeof(*(&a[0]+1)16字节*(&a[0]+1)==a[1],构成sizeof(a[1]),表示这一行所有元素sizeof(*a)16字节*a=a[0],构成sizeof(a[0]),表示这一行的所有元素sizeof(a[3])16字节越界访问,但sizeof不管,依旧往下找4个元素凑成一行计算大小 指针运算笔试题解析 第一题

 解答: &a+1==跨过这个数组之后的地址,强制转化int *类型赋给int 指针ptr

            *(a+1)==*(&a[0]+1)==*(&a[1])==a[1]  所以第一空为 1

            *(ptr - 1)==*(跨过这个数组之后的地址 - 1)==*&a[5]  所以第二空为 5

注意: 这里不能将&a+1直接代入,因为这两个 1 的意义是不一样的,+1是+1×20字节

            -1是-1×4字节     

           整个数组的地址与数组首元素地址大小相同,所以跨过这个数组之后的地址大小与数组最后一位元素的地址加4相同,由于后面没有数组,默认为单元素的地址。

第二题

 解答: p是一个结构体指针,将十六进制数据 100000强制类型转化为一个结构体地址赋给p

 由于x86条件下,地址是32位,所以p赋得的地址是0x00100000     

            第一问 p+ 0x1,这里的1是十六进制数据,看着面生不太熟,所以我们把它转成十进制数据,还是1,所以就是 p+1,这里的1就是20字节,因为题目已经给出结构体大小为20字节的条件,结构体型的指针+1就等于+20字节。0x00100000+20==0x00100000+0x14==0x00100014,打印出来就是001000014

            第二问 (unsigned long)p + 0x1,p==0x00100000,这里的p==0x00100000被强制转换为无符号整形数据了,结果就是0x00100000+0x1==0x00100001,打印出来00100001

           第三问 (unsigned int*)p + 0x1,p==0x00100000,这里的p==0x00100000被强制转换为无符号整形地址类型了,后面0x1转成十进制数据还是1,这里的1就是四个字节,因为无符号整形是四个字节,地址就加1就加4个字节了。p+1==0x00100000+4==0x00100000+0x4==0x00100004,打印出来就是00100004

            注意  后面的 0x1的类型是由前面p的类型决定的,对于初学者来说0x1看着面生直接化成十进制去看。

第三题

 解答:给a[3][2]赋值时用到了逗号表达式,所以赋值的情况为

a[0][0]=1,a[0][1]=3,a[1][0]=5,,a[1][1]=0,a[2][0]=0,a[2][1]=0

p==a[0]==&a[0][0],   p[0]==*(p+0)==*(&a[0][0])==a[0][0]==1

所以答案为1

第四题

 解答:定义了一个容量为四个房间(16个字节)的数组指针,二维数组是25个元素(100个字节),一行5个元素(20个字节),需要一个容量为5个房间的数组指针去装,但现在是一个容量为4个房间的数组指针去装。所以p+1==p+4个元素 而不是一行(5个元素)

第一空    &p[4][2]==&*(p[4]+2)==&*(*(p+4)+2)==&*(&a[3][2]+2)==&a[3][4]

所以就是  &a[3][4]-&a[4][2]== -4 (地址减地址是相隔元素的数量)

以十六进制打印出来  负数的十六进制需要化成补码再进行转化

-4 原码 10000000 00000000 00000000 00000100

    反码 111111111 111111111 111111111 11111011

    补码 111111111 111111111 111111111 11111100

               F       F     F        F     F        F     F        C

所以答案就是 FFFFFFFC

第二空    以十进制打印   就是 -4

第五题

解答: &aa==整个数组的地址    &aa+1==数组最后一位元素的地址+1后的地址

              aa==&a[0]     *(aa+1)==*(&a[1])==a[1]==&a[1][0]

第一空   *(pr1-1)==*(数组最后一位元素的地址+1后的地址-1)==*(&aa[1][4])==aa[1][4]==10

第二空   *(ptr2-1)==*(&a[1][0]-1)==a[1][0]==5

第六题

 解答:这里建立了一个一级指针数组a,a[0]='w'的地址(第一个字符串),a[1]='a'的地址(第二个字符串),a[3]='a'的地址(第三个字符串)。

建立了一个二级指针pa,pa==a==&a[0]

*pa==*a==a[0]=='w'的地址

相当于printf("%s\n",'w'的地址);   结果就是打印出第二个字符串 at

第七题

 这是最复杂的一题,我只能以我理解的角度为大家讲解

 解答:  各级指针内的地址分配如上图所示

第一问   **++cpp==**++(&cp[0])==**(&cp[0]+1)==**&cp[1]==*&c[2]=='p'的地址

             答案就是从p的地址开始输出字符串      即 POINT

第二问  由于第一问cpp实现了自加,它指向了&cp[1]   cpp=&cp[1]

             *--*++cpp+3==*--*(&cp[1]+1)+3==*--*&cp[2]+3==*--&c[1]+3==*&c[0]+3==c[0]+3

=='E'的地址(第一个字符串第一个'E')+3=='E'的地址(第一个字符串第二个'E')

             答案就是从'E'的地址(第一个字符串第二个'E')开始输出   即 ER

第三问  由于第二问cpp又实现了自加,它这次指向了&cp[2]   cpp=&cp[2] 

             *cpp[-2]+3==**(cpp-2)+3==**(&cp[2]-2)+3==**&cp[0]+3==*cp[0]+3==*&c[3]+3

==c[3]+3=='F'的地址+3=='S'的地址

             答案就是从'S'的地址开始输出   即 ST

第四问  cpp[-1][-1]+1==*(*(cpp-1)-1)+1==*(*(&cp[1])-1)+1==*(&c[1])+1==c[1]+1

=='N'的地址+1=='E'的地址(第二个字符串)

             答案就是从'E'的地址(第二个字符串)开始输出   即 EW

创作不易,如有错误,还请见谅,感谢您的阅读! 若您觉得这篇文章对您有帮助,可以通过以下方式进行赞赏 ​​​​​​​            微信扫一扫进行赞赏

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3