Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

199
Views
Unión como argumento de una función en C

Me pregunto si es posible usar uniones como argumentos para una función:

Digamos que tengo dos estructuras:

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

Y una unión de estos dos:

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

Quiero crear una función que admita un atributo_complejo o un atributo_genérico:

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

Sin embargo, cuando hago una llamada a esta función

 prepare_tagged_attribute(2, pointer_to_complex_structure);

me sale este error:

 passing argument 2 of 'prepare_tagged_attribute' from incompatible pointer type

Entonces, supongo que el puntero a una estructura compleja no es necesariamente un puntero de tipo union (lo cual tiene sentido)... pero entonces, ¿es posible usar uniones de esta manera?

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Si está usando GCC y está dispuesto a usar sus extensiones de idioma, puede lograr lo que está tratando de hacer con un transparent_union .

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

Las uniones transparentes están diseñadas para funciones de biblioteca que tienen múltiples interfaces por razones de compatibilidad. Por ejemplo, suponga que la función de espera debe aceptar un valor de tipo int * para cumplir con Posix, o un valor de tipo union wait * para cumplir con la interfaz 4.1BSD. Si el parámetro de espera fuera nulo *, esperar aceptaría ambos tipos de argumentos, pero también aceptaría cualquier otro tipo de puntero y esto haría que la verificación del tipo de argumento fuera menos útil. En su lugar, podría definir la interfaz de la siguiente manera:

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

En su ejemplo, declararía union_attribute así:

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

Y luego puede llamar a prepare_tagged_attribute exactamente como lo propuso.

 struct tagged_attribute* prepare_tagged_attribute(int code, union_attribute attribute) { attribute.generic_attribute->current_value = 1; // eg return NULL; // eg } prepare_tagged_attribute(code, pointer_to_complex_structure);
over 4 years ago · Santiago Trujillo Report

0

Dado que no hay polimorfismo ni sobrecarga en C, no estoy seguro de que haya una solución perfecta para esto.

Su solución funcionará, siempre que envuelva su puntero en un union_attribute :

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

Es un poco molesto tener que hacer este ajuste, por lo que una opción sería introducir una nueva función para que lo haga por ti:

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

Luego, reescriba su función prepare_tagged_attribute para tomar una union por valor en lugar de por puntero:

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

Entonces, puedes decir algo como

 prepare_tagged_attribute(2, wrap_complex(pointer_to_complex_structure));

No es perfecto, seguro, pero funciona y se verifica.

¡Espero que esto ayude!

over 4 years ago · Santiago Trujillo Report

0

Como declaró la función para tomar un argumento de unión, en realidad tiene que pasar un argumento de unión , no un puntero.

Nota al margen: si usa gcc, eche un vistazo al atributo transparent_union . Eso podría ser interesante para usted, ya que en realidad permite el uso anterior. Tenga en cuenta, sin embargo, que todavía tiene que señalar qué tipo de argumento está pasando (tanto como para la forma estándar.

Una forma posiblemente mejor sería agrupar la información de tipo y valor en una sola estructura como:

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

y pasar un puntero a tal estructura a la función. Tenga en cuenta que utiliza un campo de estructura anónimo para la unión (desde C99). De esta manera puedes referir los campos como:

 struct variable_argument s; ... s.complex = ...

Sin embargo, nunca olvide configurar s.type apropiadamente si cambia el tipo de unión.

Esta estructura en realidad relaciona sus punteros con una de las otras estructuras. Sin embargo, puede tenerlos directamente en la unión en lugar de usar punteros. Eso simplifica la asignación/liberación de memoria.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!