看到,一篇对 C++的 UNION如何被C#使用的问题帖。呵呵。内容很熟悉,包括那写结构体里面的东西,但是没办法回答,因为我曾经一度弱智到,认为C#和C sharp是两个东西。同时这玩意还要.net。我没学习他的原因一则,没时间,二则,花时间学了,究竟能用多久?以微软的作风,我不如好好学点类 UNIX上的工具。
回到正题上,无法回答C#的问题。这里就struct ,union上的东西谈下我自己的想法。书本上,和标准上说的东西我就不重复了。所以只是自己的想法。
向新手说union,我几乎不能回避struct。但前提是我只谈论的是C。其实那篇文章所写的,实际是C的union而不是C++的 union。不是我在嚼舌头,有迷糊的朋友可以google些C++的union的用法,再看看C是否支持。
在C++中,为了能对面向对象进行支持,使得union增加了对类成员方法的union的支持。但这个在C中是不存在的(没有支持的必要和存在性)
需要说明,union和struct在C里面(后面不再强调,此处不是谈C++),只是一个多数据类型的操作工具。给谁用?代码员和编译器。可以这 么说。没有union,struct的C仍然可以实现,包含了这两个保留字的所有C代码可实现的功能。只是方便程序员写代码而已。
例如我们存在描述的数据,这个数据存在不同的存储空间的字段。那么我们用struct来包裹,就非常方便。如下给出两个例子
08 | char return_TEST_S_b(_TEST_S *pt){ |
12 | char return_test_ab_b( int *p){ |
15 | int main( int argc , char *argv[]){ |
18 | re_ = return_TEST_S_b((_TEST_S *)&test_s); |
19 | re_ = return_test_ab_b(( int *)&test_s); |
以上两者实际是等同的。但_TEST_S和以下的方式完全不同。
4 | char return_test_b( char *p){ |
这是因为,对于结构体,编译器看到的,每个存储单元,包含了一个int 和 char 两个类型的存储空间。因此对数组的任何一个下标的访问,他们是针对 具体存储单元锁定后,再找寻,该单元内,对应结构体内的具体类型的存储位置。
上述两者的差别非常像,以下两中构造数据表的操作。
我们把一个 “姓名” “年龄”的人的信息,放在一个表里,每个表的记录,包含两个字段,与我们有两张表,假设,表中对应记录的位置(下标)就是唯一ID号。那么每个表都只有一个字段。其中一个是“姓名”另一个是“年龄”
因此,struct只是用于打包,或规整数据之间存储位置的逻辑关系而使用的。方便于你有效描述你的目标逻辑(任务)。
同时C语言里,struct内,是不存在函数的,因为任何函数都是一个实际存在的代码片,用于执行的,struct的目的和功能我上面说了,因此无 法将多个函数进行打包。引申一下,多个函数进行位置打包的需求是客观存在的,但情况极少,通常用在对code cache有严格要求,或者函数位置和系统内部逻辑有关联的情况下。不过由于通过增加辅助信息,可以让编译器和连接器完成上述操作,因此C没有必要去用保 留字对函数打包操作。这是C与面向对象的C++不同的地方。C++的 类的概念,本身要求存在方法。而方法本身并不是数据而是一个实现函数的模版,其成为了类的一个必要组成部分。
回到 union,其实和struct很像,之不过,union的作用是多者选一个,而不是多个数据类型的整合描述。
例如下面的例子,我们做数组的全累加
05 | #define MAX_TEST_U_NUM 10 |
06 | _TEST_U u[MAX_TEST_U_NUM]; |
08 | int acc_test_U_i(_TEST_U *pt){ |
11 | for (i = 0 ; i < MAX_TEST_U_NUM ; i++){ |
16 | char acc_test_U_c(_TEST_U *pt){ |
18 | char re = 0; //注意这里是会有溢出的,其实acc_test_U_i一样会有溢出,但此处不讨论这方面问题。 |
20 | for (i = 0 ; i < MAX_TEST_U_NUM ; i++){ |
这个和下面两个函数,对比,记住,一个是错的,一个是正确的。
03 | int acc_test_U_i( void *p){ //对 |
06 | for (i = 0 ; i < MAX_TEST_U_NUM ; i++){ |
11 | char acc_test_U_c( void *p){ //错 |
15 | for (i = 0 ; i < MAX_TEST_U_NUM ; i++){ |
因为使用union,则允许整个程序里面,即可以 p->i ,也可以p->c。这是对同一个空间良种不同数据类型操作的差异,因为要保证所有可能的操作均有效。因此,空间必须按照可选择的数据类型中,最大的 一个分布。因此,以下的char的累加是对等 _TEST_U的。
01 | char acc_test_U_c( void *p){ //对 |
06 | for (i = 0 ; i < MAX_TEST_U_NUM ; i++){ |
13 | char acc_test_U_c( void *p){ |
17 | for (i = 0 ; i < MAX_TEST_U_NUM ; i++){ |
19 | re += *pc;pc+= sizeof ( int )/ sizeof ( char ); //这个地方我不怕除法, |
20 | //因为编译器对于这类东西,会修正为常量,而不是每次弱智的去除 |
如果上述例子还是不能理解union的用法,那么下面我再做个例子,大家有兴趣可以尝试把结果打印一下。假设低位在前(LSB)的硬件系统
08 | int main( int argc , char *argv[]){ |
13 | if ( u.i == 0x01020305){ |
19 | for (i = 0 ; i < 4 ; i++){ |
22 | if (u.i == 0x04030201){ |
和我其他的灌水帖一样,这篇灌水帖,包括代码都是临时写的,没验证,有漏笔之处,还望谅解。
转载于:https://my.oschina.net/luckystar/blog/56379