sizeof 和 strlen的对比及相关例题精讲与解析 |
您所在的位置:网站首页 › 佳能g7x2和200d的内存卡是一样的吗 › sizeof 和 strlen的对比及相关例题精讲与解析 |
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的操作数如果是一个表达式,表达式的不参与计算的。 例题精讲 一维数组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字节第二个元素的地址 字符数组 例一![]() ![]() ![]() 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 |