大可爱 发表于 2018-10-12 09:09:05

想 用void 指针 代替 共用体变量的成员,如何实现

本帖最后由 大可爱 于 2018-10-12 09:41 编辑

共用体变量占据的内存是 成员中最大的那个,有了新的成员,旧的就失去作用。
时间一长,只会浪费存储空间 ,如果用void 指针 会不会好点 。
如果能实现的化,请先定义个共用体,然后用指针实现定义的共用体的功能。

calton007 发表于 2018-10-12 09:49:23

本帖最后由 calton007 于 2018-10-12 09:54 编辑

可能和楼主理解的不一样,我认为共用体有两种功能:
        (1)同一个值的不同表达形式;
        (2)把一个较大字节的对象分解成这个对象的字节的表达
下面具体谈一下:
1、同一个值的不同表达形式
        由于共用体将所有的字段重叠在内存中的相同偏移处,也就是可以对同一块内存以不同的解析方式
        假设有这样的定义:
typedef union{
        char c;
        int i;
}CharofInt;
CharofInt value;

        这样定义了共用体之后,就可以灵活使用它,想把这个变量当成 int 的时候就可以使用value.i,想把它当成 char 时就可以使用value.c       
        共用体变量 value 的 c 和 i 指向同一块内存,以不同的方式解析同一块内存

2、把一个较大字节的对象分解成这个对象的字节的表达
        浮点数在内存中是按 IEEE 754 (IEEE 二进位浮点数算术标准)存储的,现在想看看每一个字节的值就可以使用共用体
        #include <stdio.h>

int main() {
    union{
      char c;
      float f;
    }num;
    num.f = 1.0;
    int i;
    for(i =3; i>=0; i--){
      printf("%d\n",num.c);
    }
    return 0;
}
浮点数1.0在内存中的表达是:00111111 10000000 00000000 00000000
每个字节对应的整型数为:63-12800
可以看看输出结果是否相符

所以我个人认为,共用体变量的各个成员如果字节没有对齐,是没有太大的实际意义
       

       

人造人 发表于 2018-10-12 12:17:39

"时间一长,只会浪费存储空间"
你这么说的依据是什么?
为什么这么说?
给我个理由

claws0n 发表于 2018-10-12 12:30:41

1. 你从哪里启发出这样的想法?
2. 不是单片机,内存的事情先不管
3. 指针变量是指针变量,不是变量,不要充当变量使用,你会抓狂~

啊涂涂 发表于 2018-10-12 12:58:46

默默吃瓜....看各位大佬头脑风暴..{:10_260:}

FC的注册很坑 发表于 2018-10-12 13:21:26

吃瓜拿鱼币,谢谢大佬

风扫地 发表于 2018-10-12 17:13:35

本帖最后由 风扫地 于 2018-10-12 17:44 编辑

不知道你到底要干啥,尝试写写吧。
不同意楼上说的指针变量不是变量,指针变量也是变量,是特殊一点的变量,也有空间存储指针变量的值,也可以对这些值或它的存储地址做一些有意思的操作,你要愿意,一个常数都能强转为(函数)指针赋值给指针变量,然后通过这个指针变量访问特定内存或调用特定代码段。
下面程序申请了八个字节的"共用体",干啥都行~

int i = 0;
char space = {0,}; // 申请8字节的栈空间
void* p = space;
for(i = 0;i<8;i++)
{
        ((char*)p) = 0x30+i;
        printf("%c\n", ((char*)p));
}

for(i = 0; i < 4;i++)
{
   ((short int*)p) = 100+i;
   printf("%d\n", ((short int*)p));
}

for(i = 0; i < 2;i++)
{
   ((long int*)p) = 12345+i;
   printf("%d\n", ((long int*)p));
}


for(i = 0; i < 2;i++)
{
   ((float*)p) = 123.35 + i*i;
   printf("%f\n", ((float*)p));
}


for(i = 0; i < 1;i++)
{
   ((double*)p) = 123456.789456;
   printf("%f\n", ((double*)p));
}


以上代码请勿在内存未统一编码的编译环境或CPU上使用(如单片机,某些arm芯片)下使用;因为我默认了你运行的环境中所有类型的指针长度都是4字节(32位系统,4个字节所能存储的数据范文已经能覆盖所有的内存空间了),char 1字节 ,short int 2字节,long int 4字节 ,float 4字节 double 8字节,且CPU是小端的。
1.其实内存你申请下来了,在遵守访问规则的情况下,想怎么用就怎么用,不然malloc函数为什么返回值是void*型的了?就是让你自己确定那些空间的用途,如果空间很省很省,位域级别的空间都能省出来,共用体能一个bit一个bit给你管理内存;
2.共用体发明出来有它特定的需求背景和应用场合,有节省空间的效果(不然你看看TI的dsp库里面对功能寄存器的定义为啥都是用的共用体,而且还是位域级别的共用体),如果共用体能解决问题就直接用共用体吧,你自己写的自己认为的NB代码别人看不懂咋办?
3.你说的共用体会浪费空间谋求新的方法,应该举出具体例子来分析并寻求具体的方案,一概而论的话,做应用层的程序员会很累,毕竟内存管理和调度是开发编译器和开发操作系统的人的事。




大可爱 发表于 2018-10-12 22:08:51

风扫地 发表于 2018-10-12 17:13
不知道你到底要干啥,尝试写写吧。
不同意楼上说的指针变量不是变量,指针变量也是变量,是特殊一点的变量 ...

大佬讲的很详细,我水平暂时不够,过段时间再看看。

大可爱 发表于 2018-10-12 22:20:43

人造人 发表于 2018-10-12 12:17
"时间一长,只会浪费存储空间"
你这么说的依据是什么?
为什么这么说?


倒数第二条,存入一个新的成员后原有的成员失去作用。同时共用体所占的内存与成员中占字节数最多的那个成员相等。
那么我推论出,存入多次存入成员后,比如存入个double 型成员,最新的一次存入的是int 型成员,那么用大的内存存小的数据就显得浪费空间。

风扫地 发表于 2018-10-13 09:13:42

本帖最后由 风扫地 于 2018-10-13 09:45 编辑

typedef union test
{
        float f1;
        double f2;
}test_union_t;

test_union_ttest_union_s;

test_union_s.f1 = 100;

这里test_union_s一共8个字节是吧,你只用的f1的话还有4个字节空着的是吗?是这意思吗?
1.空着的4个字节无伤大雅,因为你要使用共用体就意味着着两个数据本来要分开定义,但拥有某些共性或者使用时间错开或者同样的变量你需要取不一样的名字,如果不是这样的需求面前是不需要使用结构体的,使用共用体的场合是类似“合并同类项”,本来就有内存的复用,它本是为了节省空间而设计的,用在需要用这个方式去节省空间的场合。
2.空着的4个字节可以通过指针引用出来使用,用内存申请的观点去理解任何变量的定义,定义一个变量就是申请一段空间,只要保证你是在自己申请到的空间里面做读做写操作都可以,空间如果是你的,怎么利用这段空间是你自己的事。
3.后面4个可以用一下代码访问和利用:
        第一种方法:后面四个字节按每个字节分开利用
        ((char*)&test_union_s)
        ((char*)&test_union_s)
        ((char*)&test_union_s)
        ((char*)&test_union_s)
        第二种方法:后面四个字节按每两个字节分开利用
        ((short int*)&test_union_s)
        ((short int*)&test_union_s)
        第三种方法:后面四个字节按四个字节分开利用
        ((long int*)&test_union_s)
        或
        ((float*)&test_union_s)

        打开比方:

      typedef union test
      {
          float f1;
          double f2;
       }test_union_t;
      test_union_ttest_union_s;
        test_union_s.f1 = 100;
        ((char*)&test_union_s) ='1';
        printf("%f\n",test_union_s.f1);//看看这个100被破坏没有?
        printf("%c\n",((char*)&test_union_s));
        printf("%f\n",test_union_t.f2); //打印了一个莫名其妙的数,涉及到浮点数的存储格式,不延伸讨论了。


4.共用体是为节省空间而设计,如果它不能为你节省空间或者方便你写代码,你就不要使用共用体。
       

大可爱 发表于 2018-10-13 09:23:02

风扫地 发表于 2018-10-13 09:13
这里test_union_s一共8个字节是吧,你只用的f1的话还有4个字节空着的是吗?是这意思吗?
1.空着的 ...

是那个意思。
大佬讲的很6,我需要时间消化。

小白逆天改命 发表于 2018-10-13 17:52:42

吃瓜群众围观

小白逆天改命 发表于 2018-10-13 17:53:16

谢谢

skyhook 发表于 2018-10-14 18:58:16

吃瓜拿鱼币,谢谢大佬

钱闻韬 发表于 2018-10-14 21:44:30

typedef union test
{
      float f1;
      double f2;
}test_union_t;

test_union_ttest_union_s;

test_union_s.f1 = 100;

钱闻韬 发表于 2018-10-14 21:45:09

6766{:10_266:}{:10_266:}{:10_266:}

钱闻韬 发表于 2018-10-14 21:45:42

学习{:10_257:}{:10_257:}{:10_257:}

常德水鱼村 发表于 2018-10-15 09:28:18

楼主加油!

snake_abs 发表于 2018-10-15 12:36:29

吃瓜路过

snake_abs 发表于 2018-10-15 12:37:03

吃瓜路过again
页: [1] 2
查看完整版本: 想 用void 指针 代替 共用体变量的成员,如何实现