结构体
对齐规则(三条)
- 结构体变量的首地址,必须是结构体变量中“最大基本数据类型成员所占字节数”的整数倍。
- 结构体变量中每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍。
- 结构体变量的总大小,为结构变量中“最大基本数据类型成员所占字节数”的整数倍。
struct node{
char cha;
int ia;
char chb;
};
sizeof(struct node ) = 12 //字节
为什么需要字节对齐
- 字节是内存的基本单位,理论上可以访问任意变量,但是,实际上cup并非逐字节的读取内存,而是以2,4,8,的倍数的字节来读取内存。因此,就会对数据类型的地址做出一些限制,即他的地址必须是2,4,8的整数倍。这就要求,各种数据类型在内存上按一定的规则排列,也就是对齐;
- 有的平台每次读地址都是从偶地址开始,如果存放变量在奇地址开始的地方,那么一个地址可能要读两次,然后进行拼凑,效率较低。
- 不同平台的对齐方式可能不同,如此一来,同样的结构在不同的平台其大小可能不同,二者之间发送的数据可能出现错乱。
指令对齐
/#pragma pack(1)
struct node{
char cha;
int ia;
char chb;
};
sizeof(struct node) = 6
在设计结构体时,我们既要满足对齐又要节省空间,如何做?
结构体成员按成员大小依次升序排列;
不定义结构体变量,如何计算结构体成员的相对偏移量?
无中生有:vs环境下可以运行;
#include<iostream>
using namespace std;
struct node
{
char ch1;
int i;
char ch2;
};
int main() {
node* p = NULL;
cout << (int)(&(p)->i) << endl;
return 0;
}
如何判断是大端存放,还是小段存放?
大端存储与小端存储区别如下:
小端存储:数据的高位数据放在高地址,低位数据放在低地址。
大端存储:大端与小端的数据存储方式相反。数据的高位数据放在低地址,低位数据放在高地址。
对于大小端存储判断的方式有两种:
方法一:字符指针判断
在32位平台下,int占4个字节,而char类型的指针是占一个字节的,如果我们把int强传为char类型的指针,只会保存一个字节的数据,那么我们只需要判断char里面的第一个字节和int里面的第一个字节是否是一致即可判断。
如果一致则为小端模式,反之为大端模式。
注:
下面代码我们令 int a=1 如果是小端模式,int下1会存放在在低地址处,而强传为char类型的指针,1也在低地址处,所以可以判断。
#include <stdio.h>
int main()
{
int a = 1;
if (*(char*)&a == 1)
printf( "小端模式" );
else
printf( "大端模式" );
return 0;
}
方法二:联合体判断
由于联合体所有数据共享一块地址空间,存放数据的所有成员都是从低地址开始存放,所以我们可以在联合体内定义一个int和一个char类型变量,然后在外部实例化的时候创建int变量,用char变量调用,相当于隐式类型转化,如果结果为1,则低字节存放在低地址,既是小端机器,反之大端机器。
#include <stdio.h>
union Test
{
int a;
char b;
};
int main()
{
Test t;
t.a = 1;
if (t.b == 1)
printf( "小端模式" );
else
printf( "大端模式" );
return 0;
}