由浅至深->C语言中union和enum关键字的经典问题分析

引言:由浅至深系列的第二篇文章,继续体悟语言中的一些细节!

文章向导
union的自我介绍
union与系统大小端
enum枚举的引入
真正意义上的常量?

正文

一、union的自我介绍

     ~~~~          ~~~    union(联合/共用体)在语法描述上与struct有相似之处,是一种能在同一存储空间内存储不同类型数据的数据类型,换句话说,它主要被用于存储某种既没有规律、事先也未知顺序的混合类型数据。

二、union与系统大小端

1.不可不知的union特性

     ~~~~          ~~~    为了更好地理解union使用上的特性,将其与struct进行一番对比:

struct A
{
	int i;
	char c;
};
union B
{
	int i;
	char c;
}
printf("%d\n", sizeof(struct A)); //输出5
printf("%d\n", sizeof(union B)); //输出4

     ~~~~          ~~~    上述并不是一份严格意义上的程序,但我们可从中得出一个结论:与struct不同,union只分配最大成员空间,且所有成员共享这一空间。既然是共享同一份空间,也就是可理解为共用同一个内存首地址,同时共用体中的成员都可以对这份空间进行操作,操作也是共同生效。关于操作共同生效这一点的体悟,将在接下来的系统大小端中详细论述。

2.探秘系统大小端

     ~~~~          ~~~    在引出系统大小端这个问题前,我们不妨思考下述这样一个情景:

union C
{
	int i;
	char c;
}
union C c;
c.i = 1;
printf("%d\n", c.c); //输出值为多少?

     ~~~~          ~~~    或许有读者会认为显然结果为1嘛,但令人遗憾的是这个答案并不是那么的令人满意,why? 因为这个输出值取决于系统的大小端模式,所以为了见到union的真正面貌,首先得打倒他的喽啰“大小端”呢!

  • 小端模式:低地址存储低位数据
  • 大端模式:低地址存储高位数据

     ~~~~          ~~~    显然,小端模式更符合人们直观的思维对应关系,有点懵?看看下面的图吧:
由浅至深->C语言中union和enum关键字的经典问题分析_第1张图片
     ~~~~          ~~~    上述程序片段中,已将c.i赋值为1,它在内存空间中的存储方式就如上图描述的两种情形。若为小端模式:因c.c为char型,则取到是该空间中的第一个字节数据,故输出为1;若为大端模式:同理可得,输出为0。

3.实用程序(如何检测系统大小端)

#include 

/* 检查处理器大小端
 * 若为大端模式,返回0
 * 若为小端模式,返回1
*/
int checkCPU()
{
	union w
	{
		int a;
		char b;
	}c;
	c.a = 1;
	return (c.b == 1); //判断c.b是否与1相等,小端模式下低地址中存放的是0x01,而大端模式下高地址存放的是0x01 
}

int main()
{
	printf("%d\n", checkCPU());

	return 0;
}

     ~~~~          ~~~    本程序就是基于系统大小端的原理进行编写,读者可好好体悟一番。

三、enum枚举的引入

     ~~~~          ~~~    enum是C语言的一种自定义类型,可用它创建一个新“类型”并指定其具有的值。将枚举引入的目的实际是为了提高程序的可读性,举个栗子:

enum color
{
	RED;
	BLUE = 2;
	GREEN;
};

int main
{
	int c = GREEN;
	printf("%d\n", c); //输出3
	c = RED;
	printf("%d\n", c); //输出0
	
	return 0}

上面这个例子虽然简单,可却向我们阐明了几分道理:

  • enum变量的类型实际上为int型
  • 枚举中第一个定义的值默认为0(手动指定除外)
  • 默认情况下后续定义的值为在前一个的基础上+1

四、真正意义上的常量?

     ~~~~          ~~~    C语言中常量这个问题经常会在笔试/面试题中提及,或许首先映入你的脑海中会是const、define这两个关键字,如果是,今天不妨重新认识它—enum !

  • 首先,我const郑重声明,C语言中我没法定义一个常量,很抱歉迷惑了一些初学者!如果你想得到一个只读变量,我很乐意。
  • emm,我define是可以定义一种称之为宏常量的东西,但我的本质是字面量(并不占用内存空间),仅仅是在预编译期进行文本替换而已。
  • 今天我就把话撂在这儿:我enum可以定义C语言中真正意义上的常量!不信?非要我露一手你才信服:
#include
enum  //无名枚举,用于定义常量
{
	SIZE = 10
};

void InitArray(int array[])
{
	int i = 0;
	for(i=0; i<SIZE; i++)  //here!
	{
		array[i] = i+1;
	}	
}

void PrintArray(int array[])
{
	int i = 0;
	for(i=0; i<SIZE; i++) //here!
	{
		printf("%d\n",array[i]);
	}
}

int main()
{
	int array[SIZE]={0}; //here!
	
	InitArray(array);
	PrintArray(array);
	
	return 0;
}

嗯…,希望我说明白了。Farewell,my friend!

参阅资料
C Primer Plus
高质量嵌入式Linux C编程
狄泰软件学院-C语言进阶剖析教程

你可能感兴趣的:(C/C++,语录)