编译器会为结构体变量中的每一个数据成员分配不一样的地址空间,也就是说,结构体变量中的数据程序是并列关系,而编译器为共用体变量中的数据成员分配的是同一块内存,每一个时刻只有一个数据成员有意义,从地址的角度来看二者的差别,形象地代表了这一点数组
#include <stdio.h> #include <stdlib.h> #include <string.h> //初始化方式和结构体相似 union data{ //相似于结构体变量,共享内存,共用体的大小等于最长的那一段,共用体变量在任什么时候刻只有一个成员变量存在,定义的时候不能初始化,只有在建立的时候才能初始化 int price; char brand[20]; }d1, d2, *pData, data[10]; union key{ //共用体会存在字节数填充,直到能够被最小类型字节数整除,double有8个字节,a数组有9个,再填充7个字节,刚好被double整除 //内存对齐的方式,分别CPU寻址 double d; char a[9]; } k; //sizeof(k) =16 void main(){ printf("%d\n", sizeof(d1)); //20 d1.price = 100; strcpy(d1.brand,"IBM"); d2 =d1; //共用体变量能够直接赋值 printf("%d,%s\n",d1.price,d1.brand); //5063241,IBM 只正确显示,最后一个赋值的变量,其余的数据解析为错误数据,由于他们共用一段内存 union data uniondata = {100 }; //大括号初始化时,只能初始化第一个成员变量!!!共用同一片空间 //共用体变量的三种引用方式和结构体变量相似 }
//初始化方式和结构体相似 union data{ //相似于结构体变量,共享内存,共用体的大小等于最长的那一段,共用体变量在任什么时候刻只有一个成员变量存在,定义的时候不能初始化,只有在建立的时候才能初始化 int price; char brand[20]; }d1, d2, *pData, data[10]; union key{ //共用体会存在字节数填充,直到能够被最小类型字节数整除,double有8个字节,a数组有9个,再填充7个字节,刚好被double整除 //内存对齐的方式,分别CPU寻址 double d; char a[9]; } k; //sizeof(k) =16 void main(){ printf("%d\n", sizeof(d1)); //20 d1.price = 100; strcpy(d1.brand,"IBM"); d2 =d1; //共用体变量能够直接赋值 printf("%d,%s\n",d1.price,d1.brand); //5063241,IBM 只正确显示,最后一个赋值的变量,其余的数据解析为错误数据,由于他们共用一段内存 union data uniondata = {100 }; //大括号初始化时,只能初始化第一个成员变量!!!共用同一片空间 //共用体变量的三种引用方式和结构体变量相似
结构体变量占据的内存单元的个数应当大于等于其内部全部数据成员占据内存单元数的和spa
出于效率的考虑,C语言引入了字节对齐机制,通常来讲,不一样的编译器字节对齐机制有所不一样,但仍是有如下3条通用准则:
(1)结构体变量的大小可以被其最宽基本类型成员的大小所整除;
(2)结构体每一个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,若有须要编译器会在成员之间加上填充字节(internal adding);
(3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,若有须要编译器会在最末一个成员以后加上填充字节(trailing padding)。
字节对齐第3条准则说起最宽基本类型的概念,所谓基本类型是指像char、short、int、float、double这样的内置数据类型。“数据宽度”就是指其sizeof的大小。诸如结构体、共用体和数组等都不是基本数据类型code
#include <stdio.h> #include <stdlib.h> #include <string.h> //第一步:找出最宽的基本数据类型 //第二步:每一个成员变量均可以被最宽基本类型整除 //第三步:累加 struct data1{ char c; // 4 char必须能被最宽基本类型整除,因此也是4个字节 int price; // 4 int是最宽基本数据类型 4个字节 char brand[19];// 20 数组是否是基本数据类型,基本数据是char类型,也要能被4整除 因此填充1个字节,就是20 }d1; //sizeof(d1)=28 struct data2{ char c; // 1 char必须能被最宽基本类型整除,因此也是1个字节 char price; // 1 char 是最宽基本数据类型 1个字节 char brand[19];// 19 数组是否是基本数据类型,基本数据是char类型,也要能被1整除 无需填充 }d2; //sizeof(d2)=21 struct data3{ char c; // 8 char必须能被最宽基本类型8整除,因此也是8个字节 double price; // 8 char 是最宽基本数据类型8个字节 char brand[19];// 24 数组是否是基本数据类型,基本数据是char类型,也要能被8整除, 填充5个字节,24个字节 }d3; //sizeof(d3)=40 void main(){ printf("%d\n", sizeof(d3)); printf("%x\n",&d1); printf("%x\n",&d1.c); printf("%x\n",&d1.price); printf("%x\n",&d1.brand); /* * 406400 &d1 * 406400 &d1.c +4 406404 &d1.price + 4 406408 &d1.brand +20 */ }