C++进阶—>各类型占大小及sizeof函数
来源:互联网 发布:淘宝上解封lol账号可信 编辑:程序博客网 时间:2024/06/06 01:22
本文针对32位编译器而言,64位编译器同理。
/****************************各类型所占大小*******************************/
本部分参考http://blog.csdn.net/ynnmnm/article/details/45826963,但存在改进!
#include <iostream>using namespace std;////////// 测试基础类型 //////////int GetArraySize(char str[]){ return sizeof(str);}void TestSizeofBase(){ cout << "////////// 测试基础类型 //////////" << endl; char* pStr = "hello world"; char arrStr[] = "hello world"; cout << "char: " << sizeof(char) << endl; cout << "short: " << sizeof(short) << endl; cout << "int: " << sizeof(int) << endl; cout << "float: " << sizeof(float) << endl; cout << "double: " << sizeof(double) << endl; cout << "char*: " << sizeof(pStr) << endl; cout << "string: " << sizeof("hello world") << endl; cout << "char[]: " << sizeof(arrStr) << endl; cout << "char[] as param: " << sizeof(GetArraySize(arrStr)) << endl; cout << endl;}//////////// 测试空类 ////////////class EmptyA{};class EmptyB : public EmptyA{};struct EmptyStruct{};void TestSizeofEmpty(){ cout << "//////////// 测试空类 ////////////" << endl; cout << "EmptyA: " << sizeof(EmptyA) << endl; cout << "EmptyB: " << sizeof(EmptyB) << endl; cout << "EmptyStruct: " << sizeof(EmptyStruct) << endl; cout << endl;}////////// 测试内存对齐 //////////class AlignA{ char a;};class AlignB{ char a; short b;};class AlignC{ char a; short b; double c;};#pragma pack(1)class AlignD{ char a; short b; double c;};#pragma pack()void TestSizeofAlign(){ cout << "////////// 测试内存对齐 //////////" << endl; cout << "AlignA: " << sizeof(AlignA) << endl; cout << "AlignB: " << sizeof(AlignB) << endl; cout << "AlignC: " << sizeof(AlignC) << endl; cout << "AlignD: " << sizeof(AlignD) << endl; cout << endl;}//////////// 测试多态 ////////////class VirtualA{ virtual void test();};class VirtualB{ virtual void test(); virtual void test2();};void VirtualB::test() {}void VirtualB::test2() {}class VirtualC{ char a; virtual void test(); virtual void test2();};void TestSizeofVirtual(){ cout << "//////////// 测试多态 ////////////" << endl; VirtualB objB; cout << "VirtualA: " << sizeof(VirtualA) << endl; cout << "VirtualB: " << sizeof(VirtualB) << endl; cout << "VirtualB Object: " << sizeof(objB) << endl; cout << "VirtualC: " << sizeof(VirtualC) << endl; cout << endl;}void TestSizeof(){ TestSizeofBase(); TestSizeofEmpty(); TestSizeofAlign(); TestSizeofVirtual();}int main(int argc, char **argv){ TestSizeof(); getchar(); return 0;}输出结果
简要说明
char数组在计算大小的时候分配了大小算总值,若赋了初始值除了字符数之和还要算上结束符\0.
指针类型都是占4字节,因为在32位编译器来说都是地址都是32位的无符号int型,故4字节。
sizeof(GetArraySize(arrStr)) 4,是因为参数传递为形参时,把数组转为了指针。
sizeof(空类) 1,是因为实例化类需要编译器给它分配内存空间,不能分配为size为0的内存,所以编译器默认分配了一个字节,以便标记可能初始化的类实例,同时使空类占用的空间也最少(即1字节)。
内存对齐,对象的首地址能够被其最宽基本类型成员的大小所整除;每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍, 如有需要编译器会在成员之间加上填充字节(internal adding);总大小为最宽基本类型成员大小的整数倍。
虚函数,虚函数表指针,大小相当于sizeof(void *)。
/***************************sizeof函数****************************/
本部分参考http://www.cnblogs.com/zhangyz/articles/4736758.html ,但存在改进!
学过c的都知道sizeof运算符。不过还是需要注意以下几点。先从c的sizeof说起:
1. sizeof 是运算符,而不是函数。虽然我们习惯sizeof(...),但( )并不是必需的,它只是表示优先级。我们把sizeof后面的目标叫对象或者操作数。本文约定就叫sizeof对象。
2. 当sizeof 的对象是表达式时,求的大小是表达式返回值的类型大小,但并不计算表达式的值,比如
char
c = 1;
int
i = 2;
cout <<
sizeof
(c + i) << endl;
cout <<
sizeof
(c = c + i) << endl;
前者c + i会隐式类型转化为int类型(类型提升),因此返回4(32位系统), 而后者虽然运算时也是转化为int,但赋值给c时又会转化为char,因此返回的是1。同样如果对象是函数,则返回函数返回值类型大小,如:
long
long
foo()
{
printf
(
"'%s' has been called.\n"
, __func__);
return
0;
}
int
main(
int
argc,
char
**argv)
{
cout <<
sizeof
(foo()) << endl;
return
0;
}
执行后输出8, 不会输出 'foo' has been called.说明函数没有真正执行,而只是判断了下返回类型。
3.注意sizeof 对象是指针和数组的区别。
当sizeof的对象是数组时,返回数组总大小,而当对象是指针时,返回指针本身的大小,而不是指示内存空间的大小。因为指针本身就是一个无符号整型数, 因此int *p ,sizeof(p)返回的大小是sizeof(void *), 32 位系统返回4,即32位。但注意当数组名作为实参传入函数时,会自动转化为指针类型,如下:
void
foo(
int
a[])
{
cout <<
sizeof
(a) << endl;
/* 4 */
}
int
main(
int
argc,
char
**argv)
{
int
a[] = {1, 2, 3, 4};
int
*p = a;
cout <<
sizeof
(a) << endl;
/* 16 */
cout <<
sizeof
(p) << endl;
/* 4 */
foo(a);
return
0;
}
4. sizeof 无法获取动态分配的内存大小,即使用malloc动态的分配内存,无法使用sizeof获取其大小。
5. 注意c_style字符串末尾有一个\0结束符,也需要占一个char空间,因此sizeof("1") 返回2。而strlen返回的是字符数,不包括\0结束符。
6.关于结构体类型。
理论上一个结构体所占空间是所有成员的大小总和,但由于考虑到对齐问题,会有填充字节。
struct
node
{
int
a;
char
c;
};
大小为8字节而不是5字节,填充了3字节。
注意:c语言中空struct大小为0, 而c++中空struct 大小为1, 具体看后面关于空类的讨论。另外,c99中结构体后面的动态数组,即不指定大小的数组,sizeof 时不包括动态数组的大小,即
struct
node
{
int
a;
char
c;
int
d[];
};
返回依然是8。
下面关于c++类的讨论。除了struct ,以上讨论关于c的sizeof同样适合于c++。首先说说c++ 中的struct类型,注意和c中的struct是不一样的,c中的struct只是一种把各种基本数据类型包装的组合类型,而c++的struct本质 上是类,即类有的东西,struct基本都有,即struct也有构造函数、析构函数、成员函数等等,不过它的默认成员是public的,而class定 义的类成员默认是private的。另外,struct继承默认也是public,而class定义的类默认是private。另外注意:class可以定义模板参数,但struct不可以!因此,struct本质就是类。
下面主要讨论类的大小:
1. 空类的大小。空类型实例中不包含任何信息,应该大小为0. 但是当我们声明该类型的实例的时候,它必须在内存中占有一定的空间,否则无法使用这些实例。至于占用多少内存,由编译器决定。g++中每个空类型的实例占1字节空间。注意空struct即空类,这就是为什么c++的空struct占一个字节的原因。
2. 构造函数、析构函数、成员函数调用时只需知道函数地址即可,而这些函数的地址之与类型相关,而与具体的实例无关,因此不会在实例中额外添加任何信息。
3. 静态数据成员放在全局数据成员中,它不占类实例大小,多个类实例只有一个实体。可以看作是一种特殊的全局变量。
综上1,2,3:
class
A
{
public
:
static
int
a;
static
char
c;
A(){};
~A(){};
void
foo(){};
};
类A的大小为1字节,等于空类大小,因此静态数据成员a,c和成员函数都不占类的大小。
4. 类的非静态数据成员和c语言中的struct类似,也需要对齐,可能需要字节填充。
class
A
{
public
:
int
a;
char
c;
A(){};
~A(){};
void
foo(){};
};
类A的大小为8字节,a占4B,c占1B,填充3B。
5. 如果一个类中有虚函数,则该类型会生成一个虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针,因此类大小必须加上一个指针所占的空间。如果是普通继承,子类和基类共享这个指针。
class
A
{
public
:
int
a;
char
c;
A(){};
~A(){};
void
foo(){};
void
virtual
bar(){};
};
类A的大小为12B。数据成员8B,加上指向虚拟函数表的指针。注意,是在32位系统上。如果是64位机器,一个指针占8B。
6.虚继承时,派生类会生成一个指向虚基类表的指针,占一个指针大小空间。如果还有虚函数,不增加额外指针大小空间,原因不太清楚,如果谁知道,请一定要告诉我!如下:
class
A
{
int
a;
};
class
B:
public
virtual
A
{
int
b;
virtual
void
foo(){};
};
类B的大小为12B,数据成员b占4B,从A中继承a也占4B,另外一个由于virtual存在,额外加一个指针大小4B,共12B。所以:只要有virtual,无论是在成员函数,还是在继承上,都额外加一个指针大小空间。
- C++进阶—>各类型占大小及sizeof函数
- 各类型占内存空间大小
- c语言中各类型所占字节大小
- sizeof()函数求类型所占字节大小-指针,数组
- 关于sizeof 各类型大小、类的大小
- c语言中各类型所占字节,及输出模式
- C/C++ sizeof函数解析——解决sizeof求结构体大小的问题
- C/C++ sizeof函数解析——解决sizeof求结构体大小的问题
- c语言中各类型所占字节
- c语言中各类型所占字节
- c语言中各类型所占字节
- C/C++中各类型数据所占字节数
- C语言各类型所占字节数
- C语言中,各类型数据所占字节数及与它取值范围的关系
- C语言中,各类型数据所占字节数及与它取值范围的关系
- sizeof 各数据类型占空间大小
- 各类型所占字节
- JAVA——各类型所占字节数
- C# dllimport
- 多线程编程博客推荐及phread线程的深入理解
- Python3中urllib详细使用方法(header,代理,超时,认证,异常处理)
- MFC Edit实现换行
- css3动画高级应用开发唱吧首页图片飞入效果
- C++进阶—>各类型占大小及sizeof函数
- 我们无法改变大环境,却一直在努力去更好地服务创业
- 你的创业,为什么那么怕融不到钱?
- 线上创业大赛 允许“互相伤害”
- PHP新的垃圾回收机制:Zend GC详解
- Java进制的表示方法
- java之SimpleDateFormat时间格式化
- 数据结构---C语言单链表基本操作
- 对话框