一 C++内置类型所占字节数
32位编译器
类型 | 所占字节 |
---|---|
bool | 1 |
char | 1 |
short | 2 |
int | 4 |
unsigned | 4 |
long | 4 |
unsigned long | 4 |
long long | 8 |
float | 4 |
double | 8 |
long double | 8 |
char * (指针) | 4 |
note:
- 无符号类型与有符号类型所占字节数相同
- 64位编译器:指针类型所占字节数为8,long double 在vs2017-64位编译器下占8字节,在clion-64编译器中为16, 不同平台所占字节数不同,较为少用。其它数据类型与32位编译器相同
最好自己实践一波:
std::cout << "bool :\t" << sizeof(bool) << std::endl;
std::cout << "char :\t" << sizeof(char) << std::endl;
std::cout << "short :\t" << sizeof(short) << std::endl;
std::cout << "int :\t" << sizeof(int) << std::endl;
std::cout << "long :\t" << sizeof(long) << std::endl;
std::cout << "long long :\t" << sizeof(long long) << std::endl;
std::cout << "float :\t" << sizeof(float) << std::endl;
std::cout << "double :\t" << sizeof(double) << std::endl;
std::cout << "long double :\t" << sizeof(long double) << std::endl;
std::cout << "char * :\t" << sizeof(char *) << std::endl;
std::cout << "unsigned :\t" << sizeof(unsigned) << std::endl;
std::cout << "unsigned long :\t" << sizeof(unsigned long) << std::endl;
二 用户自定义数据类型
1. 联合体的sizeof
联合体各成员共享一段内存;所以整个联合体的sizeof也就是每个成员sizeof的最大值。但是也会有字节对齐,按照最大内置数据类型的字节数对齐。
-----以下所有用例在32位,64位编译器下亲测,结果一致----
例1:
union u
{
int a;
float b;
double c;
char d[17];
};
最大数据类型为double,8字节。最大数据成员是d,占17字节,但是按照8字节对齐。联合体占内存大小:17 + 7 = 24(字节)
测试结果:24
例2:对比上例
union u
{
int a;
float b;
char c[17];
};
最大数据类型为int,4字节。最大数据成员是c,占17字节,但是按照4字节对齐。联合体占内存大小:17 + 3 = 20(字节)
测试结果:20
2. 结构体的sizeof
C++结构体字节对齐:
计算机系统对基本类型数据在内存中存放的位置有限制,要求这些数据的起始地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。
对齐规则(个人总结):
- 先寻找结构体中最大的数据类型;
- 每个结构体成员按最大数据类型所占的字节数分配内存,如果相邻的几个数据成员所需要的内存之和,少于一个最大数据类型所占的内存,则共用一个单位(最大数据类型)的内存空间。
例1:
struct MyStruct
{
char a;
int b;
double c;
};
最大数据类型为double,8字节。所以a分配8字节,剩余7字节。b与a相邻,b只需要4字节,可以存放在a中,所以b不必分配新内存,a,b共占8字节。c占8字节。结构体占内存大小:8+8 = 16(字节)
测试结果:16
例2:
struct MyStruct
{
char a;
double b;
char c;
};
最大数据类型为double,8字节。所以a分配8字节,剩余7字节,不足以存下b,所以b重新分配8字节。同理,c也占8字节。结构体占内存大小:8+8+8 = 24(字节)
测试结果:24
例3:空结构体
struct MyStruct
{
};
空结构体,在C语言中占0字节,在C++中占1字节。
测试结果:1
例4:结构体有静态成员
struct MyStruct
{
char a;
int b;
static double c; //静态成员
};
静态成员变量存放在全局数据区内,在编译的时候已经分配好内存空间,所以对结构体的总内存大小不做任何贡献;结构体占内存大小:4+4 = 8(字节)
测试结果:8
例5:结构体中包含结构体
struct E{
int a;
double b;
float c;
};
struct MyStruct
{
char a;
int b;
struct E c; //结构体成员
};
结构体E中最大数据类型是sizeof(double)=8,且sizeof(E)=8+8+8=24个字节;在结构体MyStruct中,最大数据类型取E的最数据类型8;a,b共占8字节。结构体占内存大小:8+24 = 32(字节)
测试结果:32
例6:结构体中包联合体
union U
{
int a;
double b;
char c[17];
};
struct MyStruct
{
char a;
int b;
union U c;
};
联合体U中最大数据类型是sizeof(double)=8,且sizeof(U)=17 + 7=24个字节;在结构体MyStruct中,最大数据类型取U的最大数据类型double;a,b共占8字节。结构体占内存大小:8+24 = 32(字节)
测试结果:32
例7:结构体中包数组
struct MyStruct
{
char a;
int b;
char c[5];
};
结构体中最大数据类型是sizeof(int)=4,所以c必须按4字节对齐。结构体占内存大小:4+4+5+3 = 16(字节)
测试结果:16
C++ #pragma pack宏的对齐
#pragma pack (n) //编译器将按照n个字节对齐
#pragma pack () //取消自定义字节对齐方式
3. 数组的sizeof
note:
- 当字符数组表示字符串时,其sizeof值将’/0’计算进去
- 当数组为形参时,其sizeof值相当于指针的大小
例1:
char a[10];
char n[] = "abc";
测试结果:sizeof(a) = 10,sizeof(n) = 4
例2:函数传参为数组
int func(char a[])
{
return sizeof(a);
}
Clion编译期间警告:warning: 'sizeof' on array function parameter 'a' will return size of 'char*'
测试结果:32位:sizeof(a) = 4,64位:sizeof(a) = 8
例3:sizeof求整形数组的长度!!!!!!!
int arr[] = {5,7,6,9,11,10,8};
cout << "The length of arr: " << sizeof(arr) / sizeof(int) << endl; // 输出7
int *A = new int[10];
cout << sizeof(A) << endl; // 输出4, A是指针,属于动态分配
数组名不完全等同于指针:
int intArray[10];
intArray++ // 编译出错,数组名可以被看作一个指针常量,不能被修改。
但是,数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针。失去了其常量特性,可以作自增、自减等操作,可以被修改。
4. 函数的sizeof
sizeof对一个函数调用,其结果是函数返回值类型的大小,函数并不会被报执行。
note:
- 不可以对返回值类型为空的函数求值
- 不可以对函数名求值
- 对有参数的函数,在用sizeof时,须写上实参表
例1:
int func1(int a, int b)
{
return a + b;
}
int func2()
{
return 3;
}
void func3()
{
}
测试结果:sizeof( func1(1,2) ) = sizeof( int ) = 4;
sizeof( func2() ) = sizeof( int ) = 4;
sizeof( func3() ) == 编译出错
5. 类的sizeof
与结构体的sizeof相似,类的函数不占空间,成员变量占空间,但如果包含虚函数,则类会默认包含一个虚函数表指针,无论虚函数有多少个,类的大小只会增加一个指针大小。
举例:
#include <iostream>
using namespace std;
class Base
{
public:
Base() { }
virtual void print1() = 0;
virtual void print2() = 0;
virtual void print3() = 0;
private:
int* m_pNum;
};
int main()
{
cout << sizeof(Base) << endl;
}
64位机器输出结果:
16