1 基本数据类型在不同的平台上的占用内存 不同的平台上对不同数据类型分配的字节数是不同的。
个人对平台的理解是CPU+OS+Compiler,平台的概念是三者的组合。这三者都有32位、64位之分。但通常三者是匹配的,即64位的CPU+64位的OS+64位的Comliler。
实际上数据类型实际占用的字节数是由编译器决定的!
常用数据类型对应字节数。
可用如sizeof(char),sizeof(char*)等得出。
32位编译器:
char :1个字节
char*(即指针变量,只与地址寻址范围有关): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
64位编译器:
char :1个字节
指针变量: 8个字节!!!
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节
2 关于内存对齐 首先需要注意的是,内存对齐的规则在不同的编译环境下得到的结果是完全不一样的。网上关于这方面的一些讨论起码在我的机器(linux–gcc version 7.5.0)上是得不到的正确的验证结果的。所以下面是只针对linux-gcc环境下的。
2.1内存对齐的规则 如果程序中显式的说明了内存对齐的字节数(#pragma pack(n),n为1,2,4,8,16),那么内存对齐使用下面的规则:
- 1、 对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数,这个数据成员的自身长度) 的倍数。
- 2、 在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
下面是几个例子:
#include#pragma pack(4)using namespace std;
class A
{
public:
char c1;
double d;
//大小为8字节
int i;
char c2;
};
int main()
{
A cla;
cout<<"size of A is"<
内存分布如下图所示:
文章图片
若将上面的#pragma pack(4)改为#pragma pack(8),那么得到的结果将是24。这种情况下的内存分布是:
文章图片
2.2 linux默认的内存对齐规则 【C/C++|关于linux下内存对齐的一些探究】搜集了一些资料后,比较认同下面这篇文章的观点: link.
这篇文章的观点是,在Linux gcc 下是没有默认对齐数的,默认下一次对齐到每个类型的对齐数处。
我总结的在linux下的对齐规则:
- 1、 对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是这个数据成员的自身长度)的倍数。
- 2、 在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照最大数据成员长度进行,也就是说,最后结构的大小是最大数据成员大小的整数倍
#include
//#pragma pack(8)struct test_plus
{
char a;
long double b;
char c;
};
int main(void)
{
std::cout << sizeof(long double) << std::endl;
//Long double的大小是16
std::cout << sizeof(test_plus) << std::endl;
return 0;
}
//#pragma pack()
最后输出的结果是48,如果去掉#pragma pack(8)的注释,结果将是32。
2.3 结论 最后引用上述文章中的结论:
- 首先肯定的是 linux gcc 没有默认对齐数。
- 如果他们设置了默认对齐数,可能会对其他编译器产生不兼容的问题。
- 其他的系统要求的对齐可能不相同,所以他们在 mingw-gcc on windows 做了一些改变。所以不同编译环境对齐规则是不一样的。
union实际占用的空间,是他的所有成员中,占用空间最大的一个成员的大小,再加上一定的字节对齐!!
union的对齐规则是和上面所说的是一样,也就是说:
1)如果程序中显式的说明了内存对齐的字节数(#pragma pack(n),n为1,2,4,8,16),那么内存对齐使用下面的规则:
- 1、 首先占用的空间是union中最大的那个成员的大小
- 2、 占用完初始空间后,union进行自身对齐,对齐规则是,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行
- 1 首先占用的空间是union中最大的那个成员的大小。
- 2 占用完初始的空间后,union进行自身对齐,对齐规则是,对齐将按照最大数据成员长度进行,也就是说,最后结构的大小是最大数据成员大小的整数倍
#include
using namespace std;
union u
{
double a;
int b;
};
union u2
{
char a[11];
double b;
};
union u3
{
char a[13];
char b;
};
int main()
{
cout<
也就是说,默认情况下,也就是上面说的第二种情况,根据union中最大的数据成员的大小进行对齐,也就是说,最后的大小是union成员中最大大小的整数倍。。
如果使用了#pragma pack(4),那么得到的u2的结果将会是12!!!这是因为根据#pragma pack指定的数值和联合最大数据成员长度中,比较小的那个进行。最后的结果是4的整数倍!!
推荐阅读
- string|将中文数字转换成阿拉伯数字
- CMPSC473 Malloc Lab
- C/C++|C/C++ 文件读写
- C|C语言程序设计第二版学习笔记
- 操作系统|后台开发应该读的书
- C/C++|gdb---watch使用方法
- C语言|推荐一些嵌入式、C/C++的开源库和项目
- C/C++开源库|日志系统模块基础、C语言实现一个日志模块、zlog日志模块基础
- 杂记|整数的不同进制