由浅至深->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.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
狄泰软件学院-C语言进阶剖析教程

猜你喜欢

转载自blog.csdn.net/a574780196/article/details/79965446