Union as an argument to a function in C

I am wondering if you can use unions as arguments to a function:

Let's say I have two structures:

struct complex_attribute{
    struct generic_attribute *sub_attributes[20];
};

struct generic_attribute{
    int current_value;
};

And the combination of these two:

union union_attribute{
    struct complex_attribute *complex;
    struct generic_attribute *generic;
};

I want to create a function that accepts either complex_attribute or generic_attribute:

struct tagged_attribute* prepare_tagged_attribute(int code, union union_attribute *attribute)

However, when I call this function

prepare_tagged_attribute(2, pointer_to_complex_structure);

I get this error:

 passing argument 2 of ‘prepare_tagged_attribute’ from incompatible pointer type

Therefore, I believe that a pointer to a complex structure is not necessarily a pointer to a type union (which makes sense) ... but then can unions be used this way?

+4
source share
6 answers

Since there is no polymorphism or overload in C, I am not sure if this is the ideal solution.

Your solution will work if you close your pointer to union_attribute:

union union_attribute argument;
argument.complex = pointer_to_complex_structure;
prepare_tagged_attribute(2, &argument);

, , :

union union_attribute wrap_complex(struct complex_attribute* attr) {
    union union_attribute result;
    result.complex = attr;
    return result;
}

prepare_tagged_attribute, union , :

struct tagged_attribute* prepare_tagged_attribute(int code, union union_attribute attribute)

-

prepare_tagged_attribute(2, wrap_complex(pointer_to_complex_structure));

, , .

, !

+3

GCC , , transparent_union.

https://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Type-Attributes.html:

, . , , wait int * Posix union wait *, 4.1BSD . wait *, wait , . ,   :

      typedef union
        {
          int *__ip;
          union wait *__up;
        } wait_status_ptr_t __attribute__ ((__transparent_union__));

      pid_t wait (wait_status_ptr_t);

union_attribute :

typedef union {
    struct complex_attribute *complex;
    struct generic_attribute *generic;
} union_attribute __attribute__ ((__transparent_union__));

prepare_tagged_attribute , .

struct tagged_attribute* prepare_tagged_attribute(int code, union_attribute attribute)
{
   attribute.generic_attribute->current_value = 1; // e.g.
   return NULL; // e.g.
}

prepare_tagged_attribute(code, pointer_to_complex_structure);
+3

union, union, .

Sidenote: gcc, transparent_union. , . , howeer, , ( ).

, - , :

struct variable_argument {
    enum {
        COMPLEX_ARG, GENERIC_ARG
    } type;
    union union_attribute{
        struct complex_attribute *complex;
        struct generic_attribute *generic;
    };
};

​​ . .   ( C99). , :

struct variable_argument s;

... s.complex = ...

s.type , .

. . / .

+1

( ) union_attribute*. C99, , " ", , , , . , , - , :

#include <stdio.h>

struct generic_attribute{
    int current_value;
};

struct complex_attribute{
    struct generic_attribute *sub_attributes[20];
};

union union_attribute{
    struct complex_attribute *complex;
    struct generic_attribute *generic;
};

struct tagged_attribute* prepare_tagged_attribute(int code,
                                                  union union_attribute *attribute)
{
    if (code == 1) {
        printf("in func, generic_attribute is %p\n", attribute->generic);
    } else {
        printf("in func, complex_attribute is %p\n", attribute->complex);
    }
    return NULL;
}

int main()
{
    struct generic_attribute g;
    printf("in main, generic_attribute is %p\n", &g);
    prepare_tagged_attribute(1, &(union union_attribute){.generic=&g});

    struct complex_attribute c;
    printf("in main, complex_attribute is %p\n", &c);
    prepare_tagged_attribute(2, &(union union_attribute){.complex=&c});

    return 0;
}

. . C99, ++, C, , .

+1

Do not use connections at all. Since you are also passing code indicating what type of pointer is being used, use a pointer to void and just pass a structure pointer:

prepare_tagged_attribute(2, pointer_to_complex_structure);

Then dynamically draw a pointer based on the code:

if( code == 2 ){
    struct complex_attribute* p = attribute ;
}
0
source

I would just declare a function to accept both types of arguments

prepare_tagged_attribute(struct complex_attribute *complex,struct generic_attribute *generic)

Process the first argument other than NULL.

0
source

All Articles