c++中sizeof()运算符的的深入理解(转载)

文章目录
背景:
分析:
理解分析:
[角度 1]:
[角度 2]:
[角度 3]:
[角度 4]:

简 述: 对 C / C++ 中的 sizeof() 运算符的一些深入思考;

背景:
昨晚看到一题,虽然可以轻易得到结果,但是突然深入思考一些,这是为什么?

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
char str1[] = “Hello”;
str1[2] = ‘a’;
printf("%s\n", str1);
char str2[100]=“Hello”;
char * p1 = “Hello”;
const char *p2 = p1;
sizeof(“Hello”);
sizeof(str1);
sizeof(str2);
sizeof(p1);
sizeof(p2);
printf("%d, %d, %d, %d, %d\n", sizeof(“Hello”), sizeof(str1), sizeof(str2), sizeof(p1), sizeof(p2)) ;

int a, b, c, d;
a = sizeof("123456789"); //a为10
b = sizeof("123456789"+1); //在 qt creator 和 VS 2015 结果不一致

c = strlen("123456789"); //c为9
d = strlen((const char *)("123456789"+1)); 

printf("%d, %d, %d, %d, %d, %d\n", a, b, c, d, sizeof(unsigned int), sizeof(int));
return 0;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
思考:

这里的 sizeof(“Hello”), sizeof(str1), sizeof(str2), sizeof(p1), sizeof(p2) 打印出来的值是多少?

下面一列表的 a, b, c, d, sizeof(unsigned int), sizeof(int) 打印出来的值又是多少?

分析:
理解分析:
在 win 10 + VS2015 的 x86 模式下,运行结果如下:

我的理解如下:

上一组的结果运行和分析如下:

sizeof(“Hello”) 的值是 6, 等价于 “hello\0” 应在内存中占 6 个字节,且 “hello” 是 char [6] 类型(由截图可知),但为什么不是 char * 或 const char * 呢?那就不知道了,反正编译器的规则 就是这么定的;

sizeof(str1) 的值是 6, 等价于 sizeof(char [6]) ,在内存中一共分配 1*6 个字节;下标里面的[] 中的 6 是根据赋值语句,编译器自己推算出来的;

sizeof(str2) 的值是 100, 等价于 sizeof(char [100]) ,在内存中一共分配 1*100 个字节;

sizeof(p1) 的值是 4,等价于 sizeof(char *),等价于 sizeof(指针)

sizeof(p2) 的值是 4,等价于 sizeof(const char *),等价于 sizeof(指针)

下一组的结果运行和分析如下:

a 的值是 10, 等价于 sizeof(char [10]) ,在内存中一共分配 1*10 个字节;

b 的值在不同系统,不同编译器上,结果是不一样的(eg: mac10.14.6 + qtCretor5.12.8 && win10 + vs2015); 结果不一直的原因是 无法判定 “123456789”+1 到底应该是 char [10] + int 之后,应该是什么类型?只能够根据自己的编译器实际决定;且还有一中观点: 此行是在编译时刻就已经被替换为具体的数值了,然后这一行的代码也会被删除掉,更加不会被执行,所以其 sizeof 的副作用是不会实现的(如 sizeof(++i)其实只能够等价于 sizeof(对象(变量 i )的类型),其运行时刻在计算其值是不存在的)

注意一点即可,有一个误区,以前的 类似于 int x1 = 3 + ‘b’ 能够顺利进行隐式转换,是因为知道最后应该转换为 等式 的左侧 的 int 类型;而我们这里系统没有 左值,故无法知道转换为什么类型,所以出现如下截图,此上下文不支持;

c 的值是 9,没有什么好讲的,该函数的实现,是遇到第一个 ‘\0’ 就停止;

d 的值是 8 ?(两个不同环境都是 8,有点费解),这个不明所以;查看源码 strlen() 的实现如下 size_t strlen(const char *__s);,按照我的理解,应该是等价于 d = strlen((const char *)(“123456789”+1)) 的,显示结果依旧为 8;这个结果为啥是 8, 有点费解,不过觉得没有探究的必要,也不是本文谈论的重点;此行多探究无意义,且这样写,有点 “无中生有”,“惹是生非”,“搞事情” 的感觉

sizeof(unsigned int) 的值是 4,不用解释

sizeof(int) 的值是 4,不用解释

下面是另外角度来思考此问题:

[角度 1]:
sizeof() 是 返回一个类型的在内存中说占的字节数。 是属于 运算符 , 同为 运算符 的还有 + 、-、*、/ 、% 等。而这个是在编译时候就被执行,而非运行时候执行,一开始就已经是计算机被知道的。

C 标准和实际上的 编译器 一开始就定义好了,在 32 位电脑中,int 占据 4 字节, char 占据 1 字节;

对于内置的基本数据类型 来说,下面是很容易理解,觉得一开始就被编译机在内存里面分配了这么多的变量:

sizeof(int) --> 显示 4 字节
sizeof(char) --> 显示 1 字节
1
2

而 对于 复合数据类型 来求字节大小,其是需要根据 组合的基本数据类型 来给出实际的内存中所占的字节大小,比如自定义 类:

sizeof(自定类) --> 显示 字节对齐后的 字节
sizeof(数组) --> 显示 符合类型的数组 字节
sizeof(int [4]) --> 显示 4 * 4 字节 // 这样就容易理解了
1
2
3

[角度 2]:
[p101] 类似于都是指代 《C++ primer 中文版 第5 版》一书的页码

忽然发觉有点不简单, str1 是数组类型,属于复合类型 [p101],表达式右侧 “Hello” 是什么类型(是 char [] 、 char * 还是 const char * 呢?),其实也并不重要(虽然知道了是char [6]类型 );但是它一定是给 数组 str1 赋值的;且定义的赋值写法如此

[角度 3]:
有人自己使用如下两个宏,来实现了该 sizeof() 的实现;注意的是,这是网友自己使用宏来实现的,而非 编译器 就是这样实现的,但是对于我的理解有所帮助;

//适用于非数组
#define _sizeof(T) ((size_t)((T*)0 + 1))
//适用于数组
#define array_sizeof(T) ((size_t)(&T+1)-(size_t)(&T))
1
2
3
4

[角度 4]:
sizeof 运算符,实际上有两种使用方式,且书上明确有说 sizeof 实际上并不会去计算其运算符对象的值 [p139] ,sizeof 运算时候,也不会将数组成指针来处理;

sizeof(type) // 返回 类型 在内存中所占的字节大小
sizeof expression // 返回 表达式结果的 类型 在内存中所占的字节大小
1
2

原文链接:https://blog.csdn.net/qq_33154343/article/details/107449270?utm_medium=distribute.pc_feed.none-task-blog-personrec_tag-5.nonecase&depth_1-utm_source=distribute.pc_feed.none-task-blog-personrec_tag-5.nonecase&request_id=5f1ff1399cc79f6252ce3dfe

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值