【问题标题】:How to check what type is currently used in union?如何检查联合中当前使用的类型?
【发布时间】:2013-05-13 11:01:00
【问题描述】:

假设我们有一个工会:

typedef union someunion {
    int a;
    double b;
} myunion;

是否可以在我设置后检查联合中的类型,例如一个=123? 我的方法是将此联合添加到某个结构中,并在 int 时将 uniontype 设置为 1,在 double 时将其设置为 2。

typedef struct somestruct {
    int uniontype
    myunion numbers;
} mystruct;

有没有更好的解决方案?

【问题讨论】:

    标签: c unions


    【解决方案1】:

    有没有更好的解决方案?

    不,您展示的解决方案是最好的(也是唯一的)解决方案。 unions 非常简单——它们不会“跟踪”你分配给什么。他们所做的只是让您为其所有成员重用相同的内存范围。它们不提供除此之外的任何其他内容,因此将它们包含在 struct 中并使用“类型”字段进行跟踪正是正确的做法。

    【讨论】:

    • 更好的解决方案是使用枚举值而不是 1、2 等。
    • 实际上,这种技术在内核网络编程中被广泛采用,因为接收到的数据包(数据报)的内容通常在检查头中的类型代码之前是未知的。
    • C:我的祝福就是我的诅咒
    【解决方案2】:

    C 不会自动跟踪当前正在使用联合中的哪个字段。 (事实上​​,我相信从“错误”字段读取会导致实现定义的行为。)因此,由您的代码来跟踪当前使用/填写的字段。

    您保留一个单独的“uniontype”变量的方法是一种非常常见的方法,应该可以很好地工作。

    【讨论】:

      【解决方案3】:

      无法直接查询union中当前存储的类型。

      知道存储在union 中的类型的唯一方法是使用显式标志(如在您的mystruct 示例中),或者确保当联合具有已知的活动元素。

      【讨论】:

        【解决方案4】:

        根据应用程序,如果它是一个短暂的对象,您可能能够在控制流中对类型进行编码,即。两种情况都有单独的块/功能

          struct value {
              const char *name;
              myunion u;
          };
        
          void throwBall(Ball* ball)
          {
             ...
             struct value v;
             v.name = "Ball"; v.u.b = 1.2;
             process_value_double(&v);      //double
             struct value v2;
             v2.name = "Age";
             v2.u.a = 19;
             check_if_can_drive(&v2);       //int
             ...
          }
        
          void countOranges()
          {
               struct value v;
               v.name = "counter";
               v.u.a = ORANGE;
               count_objects(&v);          //int
          }
        

        【讨论】:

          【解决方案5】:

          警告:以下仅用于学习目的:

          您可以使用一些丑陋的技巧来做到这一点(只要联合中的数据类型具有不同的大小,这是目前的情况):

          #include <stdio.h>
          
          typedef union someunion {
            int a;
            double b;
          } myunion;
          
          typedef struct somestruct {
            int uniontype;
            myunion numbers;
          } mystruct;
          
          
          #define UPDATE_CONTENT(container, value) if ( \
                                                       ((sizeof(value) == sizeof(double)) \
                                                        ? (container.uniontype = ((container.numbers.b = value), 2)) \
                                                        : (container.uniontype = ((container.numbers.a = value), 1))))
          
          int main()
          {
            mystruct my_container;
          
            UPDATE_CONTENT(my_container, 42);
            printf("%d\n", my_container.uniontype);
            UPDATE_CONTENT(my_container, 37.1);
            printf("%d\n", my_container.uniontype);
            return (0);
          }
          

          但我建议你永远不要这样做。

          【讨论】:

            【解决方案6】:

            也许我的变种有帮助

            struct Table
            {
                char mas[10];
                int width;
                int high;
                union stat
                {
                    int st;
                    char v;
                } un;
            };
            
            
            Table tble[2];
            strcpy(tble[0].mas, "box");
            tble[0].high = 12;
            tble[0].width = 14;
            tble[0].un.v = 'S';
            
            strcpy(tble[1].mas, "bag");
            tble[1].high = 12;
            tble[1].width = 14;
            tble[1].un.st = 40;
            
            //struct Table *ptbl = &tble[0];
            //ptbl++;
            
            for (int i = 0; i < 2; i++)
            {
                void *pt = &tble[i].un;
                if(*((char*)pt) == 'S')     
                    sort(put_on_bag_line);
                else
                    sort(put_on_box_line);
            }
            

            【讨论】:

            • 如果数字恰好是 83(S 的 ascii 十进制数)会怎样?而且您依赖于提前了解它可以包含的所有值。
            猜你喜欢
            • 2020-08-04
            • 2022-07-08
            • 2012-08-02
            • 2023-01-24
            • 1970-01-01
            • 2021-10-26
            • 2020-04-14
            • 2020-02-24
            • 2018-10-09
            相关资源
            最近更新 更多