程序员

首页 » 常识 » 预防 » 很多C语言程序员都知道大小端,但并不
TUhjnbcbe - 2024/2/16 15:45:00

上一节讨论了C语言的union语法的一个使用场景,读者应该发现,union成员共享一块内存的特性使得C语言程序员能够写出更加节约资源的程序。不过也有读者在看了上一节文章后,评论或者私信说了一些关于C语言union的特性,这些回复有些是不严谨的。

如果不能完全掌握union语法,在使用时难免会觉得困惑,甚至跳入“陷阱”,写出有隐患的C语言代码。我稍稍总结了一下读者回复中关于union语法的误解,主要可以分为两大类。

误区1:union成员必须等长度

下面这段C语言代码节选自上一节:

这段C语言代码节选自上一节

有读者评论称:“要是union不同成员的大小不一样就不能这么用了”。他认为C语言的union成员必须是等长的,否则就不可使用。这么认为也有一定的理由:union成员共用一块内存,如果成员不等长,那差异长度怎么算呢?

差异长度怎么算呢?

那么,C语言中的union成员到底是不是必须长度相等呢?下面是一个例子,请看:

C语言中的union成员

显然,成员c和i长度并不相等,那是否这么定义u就不对了呢?我们编写相应的C语言代码测试之:

测试C语言代码

编译这段C语言代码并执行,得到如下输出:

输出

可见编译器并没有报错。虽然我们仅使用了union的成员c(占用1字节),但是test仍然占用了4个字节。显然,即使union的成员不等长,使用起来也完全没有问题,而且union占用内存的空间等于最长的那个成员占用的内存空间。

误区2:使用union必须考虑大小端问题

有读者(

Fishmoo)回复说:“共用体(union)要在确定硬件大小端的情况下使用”。这个观点对不对呢?在回答这个问题之前,首先需要了解“大小端”的概念。

简单来说,“大小端”是指数据在内存中的字节顺序。例如int型变量a=0x占用4个字节,在大端字节序的机器上,int数据的高位位于低地址。在小端字节序的机器上,int数据的高位位于高地址。

“大小端”

关于“大小端”这个名称,有一段比较有趣的故事:

Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。据估计,先后几次有余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。这个其实讽刺当时英国和法国之间持续的冲突。DannyCohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。

那么,大小端和union有什么关系呢?读者应该明白,C语言中union语法最重要的性质就是成员共享一块内存区域,我们改写上面的C语言代码:

改写上面的C语言代码

因为在我的机器上,成员i占用4个字节内存空间,所以将成员c改为数组charc[4]。现在编写下面这段C语言代码:

C语言代码

这段C语言代码会输出什么呢?因为成员c和成员i共享同一块内存,所以c在内存中的起始地址和i的一致,i是一个4字节变量,它的值在内存中分布因机器“大端”和“小端”而异。编译这段C语言代码并执行,得到如下输出:

#gcct.c#./a.out0xxxx12

可见,高位在低地址,此时C语言程序运行在“大端”机器上。读者可自行测试上面这段C语言代码,应该会发现,如果自己的机器是“小端”架构,则C语言程序最终的输出会与这里有一定的差异。

现在知道“大小端”与C语言union的关系了。那是不是只要使用union,就一定要考虑“大小端”问题呢?当然不是了,例如上一节中的union例子,就完全不需要考虑“大小端”问题。只有涉及到使用“小变量”解释“大变量”内存区域时,才需要考虑“大小端”问题。

看了本专栏之前文章的读者应该明白,C语言中的数据类型的一大作用就是告诉编译器该如何解释它所在内存里存放的数据的。例如一个4字节内存区域:

4字节内存区域

编译器要将这块内存里的数据取出使用,先要知道该怎么取——它这块内存可以表示4个char型变量,也可以表示2个short型变量,还可以表示1个int型变量。如果告诉编译器这段内存表示一个int型数据,编译器会自动按照当前机器的“大小端”解释这个数据,就无需程序员再多操心了。如果告诉编译这段内存表示4个char型变量(小变量),则编译器会按照地址顺序解释这段内存,输出就与“大小端”有关了。

小结

本节简要介绍了C语言union语法的性质,较为详细的讨论了上一节读者关于union的两个误区。现在应该明白,C语言的union成员不一定是等长的,使用union并不总是需要考虑“大小端”问题。事实上,“大小端”问题不是union语法的专属考虑,在C语言程序开发中,很多情况都需要考虑这个问题,以后有机会再说了。

点个赞再走吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就

1
查看完整版本: 很多C语言程序员都知道大小端,但并不