引言:由浅至深系列的第二篇文章,继续体悟语言中的一些细节!
文章向导
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.i赋值为1,它在内存空间中的存储方式就如上图描述的两种情形。若为小端模式:因c.c为char型,则取到是该空间中的第一个字节数据,故输出为1;若为大端模式:同理可得,输出为0。
3.实用程序(如何检测系统大小端)
#include <stdio.h>
/* 检查处理器大小端
* 若为大端模式,返回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<stdio.h>
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语言进阶剖析教程