Linux-----结构体与联合体,大小端模式
目录
结构体和联合体
结构体:
联合体:
大小端模式
大端
小端
判断自身环境是大端还是小端
结构体和联合体
结构体:
结构体会存在字段对齐的情况:
#include <stdio.h>
struct Fitz {
char b;
int a;
};
int main(int argc, char const *argv[])
{
struct Fitz fitz;
printf("%d\n", sizeof(fitz));
return 0;
}
案例,判断下面结构体字节数:
struct data {
char name[10];
int age;
};
答案:16个字节
一个int 是4字节,上面有10个char,需要10个字节,根据结构体字段空间对齐的特性,应该按照4个字节划分,应该划分为4,4,4,4,第三个4实际上只存储了2个char类型,所以整体就是16个字节,如果按照下面的情况的话就存储满了,刚好满16字节。
struct data { char name[10]; char a; char b; int age; };
struct data {
char name[10];
int age;
char a;
};
答案: 20个字节
划分为4,4,4,4,4,最后一个char需要另外一个4字节空间
struct data {
char name[10];
int age;
char a;
};
struct node {
struct data d;
struct node* next;
};
答案:node是32字节
在64位操作系统指针一般是8字节,32位是4字节,所以根据结构体对齐划分应该是8,8,8,8 所以一共32字节。64为操作系统为例:对于data这个结构体,原本是20个字节的,划分为4,4,4,4,4,如果扩展为8位的话,前两个4组成一个8,中间两个4组成一个8,剩下最后一个4扩展为一个8,所以划分8,8,8,一共24字节,最后加上指针占8字节,总共32字节。
联合体:
这玩意跟结构体写法上很像,比如
union main
{
char name[10];
int age;
};
在 union
中,所有成员共享相同的内存区域,因此 union
的大小是它 所有成员中占用空间最大的成员的大小,并可能进行适当的对齐填充,对齐方式如下:
- 能够容纳成员中最大空间的成员的大小;
- 大小必须是对齐单位的倍数,而对齐单位取决于成员中对齐要求最大的成员。
所以根据这两个规则,上面那个联合体大小应该是12,首先选取对齐单位,显然是int 为4自己,然后最大成员是char name[10]是10字节,所以选择4最小倍数能大于10,所以是12字节。
然后就是联合体值的问题,这里跟结构体不一样,结构体每一个成员都有自身的空间,所以你可以对这些成员分别赋值,但是联合体你只能选择其中一个成员赋值,如果第二次选择另外一个成员赋值的话就会把上一个成员清空掉,因为大家都是共享内存的,等于擦掉黑白重新写字一样。
union main fitz;
strcpy(fitz.name, "fitz");
fitz.age = 18;
printf("%s\n", fitz.name);
printf("%d\n", fitz.age);
大小端模式
参考:什么是大小端?如何确定大小端?-CSDN博客
大小端(Big-endian 和 Little-endian)是计算机存储数据的一种方式,描述了多字节数据在内存中的排列顺序。
看下面案例就明白了。
大端
说白了就是高位数据存放在低地址,低位数据存放高地址
小端
高位数据存放在高地址,低位数据存放低地址
判断自身环境是大端还是小端
很简单,一个联合体就搞定了。成员只需要使用一个short类型(两个字节),还有两个连续char类型即可,然后对short类型赋值,方别查看低地址的char类型和高地址char类型对应的值是什么就行了:
#include <stdio.h>
union main
{
short a;
char b[2];
};
int main(int argc, char const* argv[])
{
union main fitz;
fitz.a = 0x1234;
printf("%x\n", fitz.b[0]);
printf("%x\n", fitz.b[1]);
return 0;
}
可以看出输出结果低地址对应的是低位的0x34,高地址对应的是高位0x12,显然就是小端模式。