联合体的声明和结构体类似,但他的行为却和结构体不同。联合体所有成员引用的是内存中相同位置。当你想在不同时刻把不同东西存在同一个位置时可以使用联合体。 看一个简单的例子。

union {
	float f;
	int i;
}fi;

fi.f = 3.14159;
printf("fi.i = %d\n", fi.i);

在一个浮点型和整形都是32位的机器上,变量fi只占据内存中一个32位字,当f被使用时,这个字就作为浮点型值被访问;单i被使用时,这个字就作为整形值被访问。简单说就是同一块内存,被翻译成不同类型的数据,如何翻译取决于定义的数据类型。 上面程序运行结果。

fi.i =  1078530000

联合体的作用

为什么使用联合体,当你只想看浮点型数如何存储在一种特定的机器上,但对其他类型不感兴趣时,联合体可能适合你。看一个例子。

BASIC需要记住程序使用的变量值,他提供了几种不同类型的变量。每个变量的类型必须和他的值一起存储。这里定义了一个结构用来存储这种信息,但是效率并不高。

struct VARIABLE{
	enum {INT, FLOAT,STRING} type;
	int   int_value;
	float  float_value;
	char    *string_value;
};

当BASIC程序中一个变量被创建时,就创建一个这种类型的结构用来记录变量的类型,根据变量的类型,把变量的值存储在三个字段中的一个。这个结构的低效之处在于,每次都有两个字段被浪费,因为一个变量只有一种数据类型。 联合可以减少这种浪费,把三个字段存储在同一块内存区域并不会产生冲突,在某个时刻,联合中只有一个字段会被使用。

struct VARIABLE {
	enum { INT, FLOAT, STRING} type;
	union {
		int    i;
		float  f;
		char   *s;
	}value;
};

如果联合体的各个成员具有不同的变量,联合的长度等于最长成员的长度

联合体-变体记录

内存中某个特定的区域将在不同时刻存储不同类型的值,在有些情况下,这些值比简单的整型或浮点型更为复杂,它们每一个都是一个完整的结构。 这个例子取自一个存货系统,他记录两个不同实体:零件(part)和装配件(subassembly)。

struct PARTINFO {
	int  cost;
	int   supplier;
	...
};
struct SUBASSYINFO {
	int  n_parts;
	struct {
		char  partno[10];
		short  quan;
	}parts[MAXPARTS];
};

接下来的存货(inventory)记录了包含每个项目的一般信息,包括一个联合,或者用于存储零件信息,或者用于存储转配件信息。

struct INVREC {
	char partno[10];
	int quan;
	enum {PART, SUBASSY} type;
	union {
		struct PARTINFO part;
		struct SUBASSYINFO  subassy;
	}info;
};

在一个成员长度不同的联合体里,分配给联合体的内存数量取决于最大成员长度。如果这些成员长度相差悬殊,当存储长度较短成员时会浪费内存,在这种情况下更好的方法是在联合体重存储指向不同成员的指针,而不是存储成员本身。所有指针的长度都是相同的,这样就解决内存浪费的问题。当决定存储那个成员时,分配正确数量的内存来存储该成员。

联合的初始化

联合变量可以被初始化,但这个初始值必须是联合的第一个成员的类型,而且它必须位于一对花括号内。例如,

union {
	int   a;
	float  b;
	char   c[4];
}x = {5};

x.a 初始化为5. 我们不能把这个变量初始化为一个浮点型或者字符值。如果给出的类型是任何其他类型的值,会被强制转化为整型并赋值给x.a。

一、 基本概念

枚举enum就是英文enumerate的缩写,也就是列举、排列说明的意思。枚举类型是C语言中的一种特殊类型,枚举类型可以让我们的程序使用一些固定长度和固定数值的变量值范围。定义枚举类型:enum 枚举类型 {枚举值列表};

二、枚举类型的使用

1、定义枚举类型

//枚举颜色
enum color{red=1, oreange=2, yellow=3, green=4, ching=5, blue=6, purple=7};

//枚举一个星期的每一天
enum week
{
	Su, Mo, Tu, We, Th, Fr, Sa
};

//枚举每一个月
enum month
{
	January, February, March, April, May, June, July, August, September, October, November, December
};

这样枚举出来的都是一推变量,引用时:

printf("%-3d %-3d %-3d %-3d %-3d %-3d %-3d", red, oreange, yellow, green, ching, blue, purple); 

也就是直接使用,会直接输出对应的值。

2、定义枚举类型的变量

enum week a, b, c;
a = Su;
b = Mo;
c = Tu;
 
enum month d, e, f;
d = January;
e = February;
f = March;

3、调用枚举类型变量 每周的日期和每月份的输出也是这样:

enum week a, b, c;
a = Su;
b = Mo;
c = Tu;
printf("%d %d %d\n", a, b, c);
enum month d, e, f;
d = January;
e = February;
f = March;
printf("%d %d %d\n", d, e, f);

4、如果在定义枚举类型时指定元素的值,也可以改变枚举元素的值 例如: enum weekday{sun=7,mon=1,tue,wed,thu,fri,sat}day; 这时,sun 为 7,mon 为 1,以后元素顺次加 1,所以 sat 就是 6 了。

5、枚举值可以用来作判断 例如: if (day==month) {…} if (day>month) {…} 枚举值的比较规则是:按其在说明时的顺序号比较,如果说明时没有人为指定,则第一个枚举元素的值认作 0。

6、一个整数不能直接赋给一个枚举变量,必须强制进行类型转换才能赋值

三、枚举案例

#include <stdio.h>
void main() 
{ 
	enum weekday {sun,mon,tue,wed,thu,fri,sat} day; 
	int k; 
	printf("请输入0到6的数:"); 
	scanf("%d",&k);
	day=(enum weekday)k; 

	switch(day) 
	{ 
		case sun: printf("sunday\n");break; 
		case mon: printf("monday\n");break; 
		case tue: printf("tuesday\n");break; 
		case wed: printf("wednesday\n");break; 
		case thu: printf("thursday\n");break; 
		case fri: printf("friday\n");break; 
		case sat: printf("satday\n");break; 
		default: printf("input error\n");break; 
	} 
} 

输入0-6中的一个数字,能够输出对应的星期。