【c++】【转】C++ sizeof 使用规则及陷阱分析
http://www.cnblogs.com/chio/archive/2007/06/11/778934.html
sizeof不是函数,更像一个特殊的宏,它是在编译阶段求值得。sizeof作用范围内即()里面的内容是被替换成类型
int a = ;
cout << sizeof( == ) << endl;
cout << sizeof(a = ) << endl;
cout << a << endl;
输出1,4,0
sizeof有两种用法:
(1)sizeof(object) 或 sizeof object
也就是对对象使用sizeof,也可以写成sizeof object 的形式
(2)sizeof(typename)
也就是对类型使用sizeof,注意这种情况下写成sizeof typename是非法的
int i = ;
cout << sizeof i << endl;//正确
cout << sizeof int << endl;//错误
基本数据类型的sizeof
(1)C++内置数据类型
char,short int(short),int,long int(long),float,double, long double,long long大小分别是:1,2,4,4,4,8, 8, 8
unsigned不能影响sizeof的取值。
(2)函数类型
int f1(){ return ; }
double f2(){ return ; }
void f3(){ return; }
void main()
{
cout << sizeof(f1()) << endl;//输出4
cout << sizeof(f2()) << endl;//输出8
cout << sizeof(f3()) << endl;//编译时出错
cout << sizeof(f1) << endl;//编译时出错
system("pause");
}
对函数使用sizeof,在编译阶段会被函数返回值的类型取代
(3)指针问题
cout << sizeof(string*) << endl; //
cout << sizeof(int*) << endl; //
cout << sizeof(char****) << endl; //
(4)数组问题
char a[] = "abcdef";
char b[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
int c[] = { , };
char d[][] = { "aa", "bb" };
cout << sizeof(a) << endl; // 7, 表示字符串
cout << sizeof(b) << endl; // 6, 仅表示字符数组
cout << sizeof(c) << endl; //
cout << sizeof(d) << endl; //
cout << sizeof(*a) << endl;//
cout << sizeof(*b) << endl;//
cout << sizeof(*c) << endl;//
cout << sizeof(*d) << endl;//
注意陷阱:(数组名与指针的区别)
int *d = new int[];
cout<<sizeof(d)<<endl; //
(5)向函数传递数组的问题。
数组名作为函数参数时会自动退化成同类型的指针
复杂数据类型中sizeof及其数据对齐问题
(1)、union的sizeof问题与cpu的边界对齐
考虑下面问题(默认对齐方式):
void main()
{
union u//8对齐
{
double a;
int b;
};
union u2//4对齐
{
char a[];
int b;
};
union u3
{
char a[];
char b;
}; cout << sizeof(u) << endl;//
cout << sizeof(u2) << endl;//
cout << sizeof(u3) << endl;//
system("pause");
}
union的大小取决于它所有的成员中,占用空间最大的一个成员的大小。所以对于u来说,大小就是最大的double类型成员a了,所以sizeof(u)=sizeof(double)=8。但是对于u2和u3,最大的空间都是char[13]类型的数组,为什么u3的大小是13,而u2是16呢?关键在于u2中的成员int b。由于int类型成员的存在,使u2的对齐方式变成4(4字节对齐),也就是说,u2的大小必须在4的对界上,所以占用的空间变成了16(最接近13的对界)。
结论:复合数据类型,如union,struct,class的对齐方式为成员中对齐方式最大的成员的对齐方式。
(2)、struct的sizeof问题
因为对齐问题使结构体的sizeof变得比较复杂,看下面的例子:(默认对齐方式下)
void main()
{
struct s1
{
char a;
double b;
int c;
char d;
};
struct s2
{
char a;
char d;
int c;
double b;
};
cout << sizeof(s1) << endl;//
cout << sizeof(s2) << endl;//
system("pause");
}
这里数据对齐与struct中元素的顺序相关. 上面例子中只是改变了struct中成员的定义顺序
同样是两个char类型,一个int类型,一个double类型,但是因为对界问题,导致他们的大小不同。
计算结构体大小可以采用元素摆放法,我举例子说明一下:首先,CPU判断结构体的对界,根据上一节的结论,s1和s2的对界都取最大的元素类型,也就是double类型的对界8。然后开始摆放每个元素。
对于s1,首先把a放到8的对界,假定是0,此时下一个空闲的地址是1,但是下一个元素d是double类型,要放到8的对界上,离1最接近的地址是8了,所以d被放在了8,此时下一个空闲地址变成了16,下一个元素c的对界是4,16可以满足,所以c放在了16,此时下一个空闲地址变成了20,下一个元素d需要对界1,也正好落在对界上,所以d放在了20,结构体在地址21处结束。由于s1的大小需要是8的倍数,所以21-23的空间被保留,s1的大小变成了24。

对于s2,首先把a放到8的对界,假定是0,此时下一个空闲地址是1,下一个元素的对界也是1,所以b摆放在1,下一个空闲地址变成了2;下一个元素c的对界是4,所以取离2最近的地址4摆放c,下一个空闲地址变成了8,下一个元素d的对界是8,所以d摆放在8,所有元素摆放完毕,结构体在15处结束,占用总空间为16,正好是8的倍数。

对于struct,class,union中各个成员在摆放时,地址需要是该成员类型大小的整数倍,同时整个struct大小是最大成员对齐大小的整数倍
类class 中的sizeof特别探讨
(1)不带virtual函数时
class A{};
class B
{
private:
int value;
double a;
};
void main()
{
cout << sizeof(A) << endl;//1,使得A的不同的对象在内存中都有着独特的地址
cout << sizeof(B) << endl;//
system("pause");
}
(2)带virtual函数时
class A
{
public:
virtual void foo(){}
private:
int m1;
double m2;
};
class B
{
public:
virtual void foo(){}
private:
double m2;
int m1;
};
void main()
{
cout << sizeof(A) << endl;//
cout << sizeof(B) << endl;//
system("pause");
}
不懂
【c++】【转】C++ sizeof 使用规则及陷阱分析的更多相关文章
- C/C++ 知识点---sizeof使用规则及陷阱分析(网摘)
C/C++ 知识点---sizeof使用规则及陷阱分析 原文出处:[胖奇的专栏] 1.什么是sizeof 首先看一下sizeof在msdn上的定义: The sizeof keyword gi ...
- 【转】【C++专题】C++ sizeof 使用规则及陷阱分析
提示:下文例子都经过Visual C++ 6.0验证,平台为win32 Windows. 一.什么是sizeof 首先看一下sizeof在msdn上的定义: The sizeof keyword gi ...
- 对C语言中sizeof细节的三点分析
转自对C语言中sizeof细节的三点分析 1.sizeof是运算符,跟加减乘除的性质其实是一样的,在编译的时候进行执行,而不是在运行时才执行. 那么如果编程中验证这一点呢?ps:这是前两天朋友淘宝面试 ...
- YII用户注冊和用户登录(三)之模型中规则制定和分析
3 模型中规则制定和分析 YII模型主要分为两类,一个数据模型,处理和数据库相关的增删改查.继承CActiveRecord.还有一个是表单模型,继承CFormModel.不与数据库进行交互.操作与数据 ...
- MyBatis参数绑定规则及原理分析
MyBatis参数的传递有几种不同的方法,本文通过测试用例出发,对其中的方式进行总结和说明,并对其部分源码进行分析. 一.测试用例(环境参考之前博客SSM接口编程一文 http://www.cnblo ...
- epoll ET模式陷阱分析
0. 前言 这篇文章主要记录在使用epoll实现NIO接入时所遇到的问题. 1. epoll简介 epoll是Linux下提供的NIO,其主要有两种模式,ET(Edge trige)和LT(Level ...
- apidoc快速生成在线文档,apidoc生成静态文件的生成规则以及原理分析
在老大的指引下,需要将系统的json文件格式转换成apidoc的json格式,也就是json格式的重组,但是这个apidoc的生成格式是不固定的,因为apidoc有自己一套的生成规则,我需要研究一下是 ...
- java中DelayQueue的一个使用陷阱分析
最近工作中有接触到DelayQueue,网上搜索资料的时候发现一篇文章谈到DelayQueue的坑.点击打开链接 文中已经总结了遇到坑的地方,还有解决方案.不过我第一眼看一下没弄明白为什么,所以翻了翻 ...
- JAVA包装类解析和面试陷阱分析
包装类 什么是包装类 虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程,基本类型的数据不具备“对象”的特性——不携带属性.没有方法可调用. 沿用它们只是为了迎 ...
随机推荐
- sql server查看某个表上的触发器
用企业管理器查看 在某个具体的表上点右键->“所有任务”->“管理触发器”,选择所要查看的触发器
- Node.js——Buffer
介绍 JavaScript没有读取和操作二进制数据流的机制,但是 node.js 引入了Buffer 类型,可以操作TCP流或者文件流 使用Buffer可以用来对临时数据(二进制数据)进行存储,当我们 ...
- Common.Logging.dll----------配置方式,可选引用,用于日志输出
1.简介common logging是一个通用日志接口,log4net是一个具体实现. common logging可以把输出连接到其他非log类上, 如EntLib的日志.NLog等 2.使用接下来 ...
- [6818开发板]八核开发板|4G开发板|GPS开发板|嵌入式开发平台
IMX6开发板(基本型):960元 IMX6开发板(豪华型):1460元 S5P4418 核心板可以无缝支持核心系统S5P6818,并保持底板设计不变,将兼顾更高端 的应用领域,为项目和产品提供更好的 ...
- laravel jwt 做API 退出登录(注销) 该怎么弄? 如何让token失效
laravel jwt 做API 退出登录(注销) 该怎么弄? 如何让token失效 php框架 laravel 2.1k 次浏览 问题对人有帮助,内容完整,我也想知道答案0问题没有实际价值,缺少关键 ...
- Spring Cloud练习1
pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...
- PHP生成文档,并把数据加入文档的小案例
PHP生成文档,可以利用file_put_contents($filename, $data),其中$filename表示文档名,$data表示需要放入的数据, 若存放的是数组,这还需要使用seria ...
- 诊断:RHEL7安装11.2RAC时root.sh错误ohasd failed to start
RHEL 7.5中安装11gRAC时,在grid infrastructure的root.sh执行时,报错: # /oracle/product/11g/grid/root.sh ... Adding ...
- 洛谷——P1731 [NOI1999]生日蛋糕
P1731 [NOI1999]生日蛋糕 搜索+剪枝 常见的剪枝: 若当前状态+后面所要搜索的最差的状态$>$或是$<$最后的状态,就返回 预处理最差的状态 #include<iost ...
- 51nod 1175 区间第k大 整体二分
题意: 一个长度为N的整数序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,第K大的数是多少. 分析: 仅仅就是一道整体二分的入门题而已,没听说过整体二分? 其实就是一个分治的函数 ...