7

C语言陷阱与技巧第33节,联合体union的使用场景是什么?它能解决什么问题?为什么要使...

 3 years ago
source link: https://blog.popkx.com/c%E8%AF%AD%E8%A8%80%E9%99%B7%E9%98%B1%E4%B8%8E%E6%8A%80%E5%B7%A7%E7%AC%AC33%E8%8A%82-%E8%81%94%E5%90%88%E4%BD%93union%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%E6%98%AF%E4%BB%80%E4%B9%88/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

C语言陷阱与技巧第33节,联合体union的使用场景是什么?它能解决什么问题?为什么要使用union语法?

发表于 2019-07-25 07:07:32   |   已被 访问: 455 次   |   分类于:   C语言   |   暂无评论

C语言中的结构体语法是非常重要,也是非常有用的,相信看了最近几节的读者应该明白。事实上,在实际的C语言项目开发中,为了代码的简洁性,描述问题时很难离开结构体。

“相同信息”的困扰

例如上一节,用于描述视频信息时,可如下定义结构体:

struct video_info{
     char *name;
     long address;
     int size;
     int alg;
     time_t time;
};

这样一来,在C语言代码中只需一个结构体变量就可用于描述视频的名称、地址、时间等信息,而无需定义多个变量,整个代码就显得非常简洁了。更为方便的是,如果今后需要增加对视频的描述,也仅需对 video_info 新增一个成员而已,例如:

struct video_info{
     ...
    int crc32;
};

有视频的地方常常也会有音频,所以我们的C语言程序还需要描述音频信息。音频信息也包括名称、地址、时间等信息,不过它也有与视频不同的参数,例如采样率,通道数。所以使用C语言描述音频信息,可以使用下面这个结构体:

struct audio_info{
     char *name;
     long address;
     int size;
     time_t time;
    int sample_rate;
    int chnnl_cnt;
};

这样一来,C语言程序描述视频和音频就简单了,只要使用 video_info 和 audio_info 结构体就可以了:

// 视频
struct video_info vinfo;
// 音频
struct audio_info ainfo;

不过,细心的读者应该能够注意到 video_info 和 audio_info 仅个别成员不同,所以似乎可以这样:

struct av_info{
    char *name;
     long address;
     int size;
     int alg;
     time_t time;
    int sample_rate;
    int chnnl_cnt;
};

上述C语言代码将视频和音频的描述结构体合二为一,以后需要描述视频和音频时,都使用 av_info 结构体:

// 视频
struct av_info vinfo;
// 音频
struct av_info ainfo;

不过,这样虽然将 video_info 和 audio_info 的重复代码合并了,但是却也导致代码的耦合性增强:用于描述视频的 vinfo 也能访问音频才有的 chnnl_cnt,用于描述音频的 ainfo 也能访问视频的 alg。

当然,程序员可以在写C语言代码时限制 vinfo 访问音频成员,限制 ainfo 访问视频成员,但是这样也会带来内存的浪费:使用 vinfo 时,音频成员占用的内存被浪费,使用 ainfo 时,视频成员占用的内存被浪费。

union 语法大显身手

可能有读者认为,视音频共用合并后的 av_info 结构体浪费的内存很小,可以不做考虑。但是应该明白,C语言程序常用语资源比较紧张的嵌入式设备中,因此合格的C语言程序员应该都是“抠门”的,尽可能的节约资源。

那这种情况下,C语言有没有办法,既能避免重复代码,又能避免耦合,同时还能节约资源呢?自然是有的,C语言中的 union 语法就是为此而设计的:

struct video_info{
     int alg;
     time_t time;
};
struct audio_info{
     int sample_rate;
    int chnnl_cnt;
};
struct av_info{
    char *name;
     long address;
     int size;
    union{
        struct video_info video;
        struct audio_info audio;
    };
};

因为视音频都有名称、地址、大小信息,所以 av_info 中的 name,address,size 成员在描述视频和音频时都会被使用。视音频具有差异的几个成员则使用 union 描述,union 中的 video 和 audio 共用一块内存区域

// 视频、音频
struct av_info av;

此时访问视频的编码算法和时间信息,可以如下实现:

alg = av.video.alg;
time = av.video.time;

访问音频的采样率和通道数,可以如下实现:

sr = av.audio.sample_rate;
cc = av.audio.chnnl_cnt;

从上面这几行C语言代码可以看出,此时视音频的相同成员公用,差异成员则通过 union 区分,这就避免了代码重复,也避免了代码耦合。另外,由于union 中的 video 和 audio 共用一块内存空间,内存浪费的问题也解决了。

本节主要讨论了C语言中 union 语法的使用。容易看出,合理的使用 union 语法,可以解决结构体难以解决的问题。

阅读更多:   C语言


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK