共用体、大端小端的判断、枚举
1、联合体(共用体)
union U { char s[9]; int n; double d; };
联合体和结构体的定义和使用是一样的,就不详细的赘述。必须要记住:联合体所有的成员变量都是共享同一块内存的,从相同的起始地址进行赋值。也就是给联合体的一个成员变量赋值的时候,就会改变其他成员变量的值。
联合体的大小:
对于计算一个联合体的大小(共用体)来说,不同的编译器计算的结果是不同的。
VS2013:
union U { char s[9]; int n; double d; }; int main(int argc, char *argv[]) { union U aa; printf(" sizeof(union U) = %d\n", sizeof(aa)); while (1); }
打印的结果是:16。分析:联合体的大小满足两个条件:(1)max(成员变量),所以分配的最大的空间是 9 个字节;(2)联合体的大小必须是成员变量类型大小的整数倍;所以,结合上下的两个条件,联合体的大小就是 16。
GCC :
gcc 计算的结果等于 12 个字节。经过多次的测试,gcc 对于内存的对齐的要求是 4 个字节。
结构体和联合区的区别:
(1)结构体和联合体都是由多个不同的类型成员组成的。但是,在同一个时候,联合体只存放了一个被选中的成员(所有的联合体公用一块地址空间),结构体的所有的成员则是都存在(不同的成员存在的地址都不相同)
(2)对于联合体的不同成员赋值,那么其他的成员将会被重写,原来的成员的值将不存在,而对于结构体来说不同的成员的赋值是互不影响的。
2、大端小端的定义
对于多字节的数据的存储来说,有16位,32位等,对于多字节的存储就必然寸在对字节安排存储的问题,这个就是大小端区别的存在。
大端模式:数据的高字节序存储在低地址中,而数据的低字节序存储在高地址中。
小端模式:数据的高字节序存储在高地址中,而数据的低字节序存储在低地址中。
3、代码
#include <iostream> using namespace std; union ud { int a; char b; }; bool ceshi() { ud c; c.a = 1; return (c.b == 1); } int main(int argc, char **argv) { if (ceshi()) { cout << "is 小端" << endl; } else { cout << "is 大端" << endl; } while (1); return 0; }
代码分析: 借助了联合体的帮助,联合体的特性存储的数据从低地址开始存储。而数据的读取也是从低地址开始读值。
分析:
a 是四个字,a = 1,也就是a = 0x00 00 00 01;当系统是大端的时候,高字节序存储在低地址,低字节序存储在高地址,那么是这么存储的
地址: 0 1 2 3 a : 00 00 00 01
b 是一个字节,当系统是是小端的时候,高字节序存储在高地址,低字节序存储在低地址,那么是这么存储的:
地址 : 0 1 2 3 a存储 : 01 00 00 00
那么b 取数值的时候,那么 b 是一个字节,这个时候,b 的值就是1
借助了联合体的帮助,当取得数值是 1 的时候,那么就是小端了。
B、使用地址的转换实现
#include<stdio.h> int main() { int test = 1; if(*(char *)&test) printf("Little endian byte order!\n"); else printf("Big endian byte order!\n"); return 0; }
分析,是因为 对于test 来说:
高字节序 低字节序 00 00 00 01
那么对 test进行强制char 类型转换,转换之后,char 是读取最低字节的内存数据,也就是说,当读取到 01 的时候,那么 01 的位置就是最低的地址,也就是 低地址保存低字节序,高地址保存高字节序,所以这个时候,就是小端了,
相反,当 char 类型读取到的数据是 00 的时候,也就是说,00这个位置是低地址,那么这个时候,低地址保存高字节序,高地址保存的是低字节序,所以,这个时候就是大端。
4、枚举
在程序的设计中,有时候会用到将有限个元素组成的集合,比如是星期一到星期天组成的集合,或者有RGB组成的集合,等等。
enum <枚举类型的名字> {x1,x2,x3,,,,};
比如:
enum weekdays {mon,tue,wed,thu,fri,sat,sun};
也就是定义了weekdays的枚举类型,它包含了七个元素。在编译器进行编译的时候,会给每个类型中的每一个元素都指定对应的整型的常量值,也称之为序号值。如果没有给指定的元素一个整型的常量值的话,那么整型的常量值是从零开始进行递增的。当将枚举类型中的除了第一个元素指定了一个常量值的话,那么前面的常量值是从零开始进行分配的,而被指定常量值的后面的部分,则是根据指定的一次递增。比如:
enum string
{x1,x2,x3=10,x4,x5,x6,x7};
那么,显然x3 已经是指定了一个常量值,则x1 = 0,x2 =1,x4 = 11, x5 = 12, x6 = 13, x7 = 14,