I just wonder, if I have a function that accept a struct that contain union inside it, how can I know the content of that union:
struct command{
int *input;
int *output;
union{
char **word;
struct command *subcommand;
} u;
};
the function:
void readCommand(command cInput){
if(cInput.u is char) print the content of array of array of char
else readCommand(cInput.u); //make a recursive call
}
any suggestion? thank you
note: I can't change the content of struct command.
You cannot. That's the nature of a union. If you need to, you must embed the union in a struct and put a type indicator in the struct.
You can't; you must assume what the underlying data is or have access to other information which can tell you what the current underlying type is. It is only valid to extract the appropriate underlying type.
If you receive objects of this type from black-box without any information about this object, there is no way to do that without changing struct command structure.
With unions, you always need some kind of a discriminator to indicate which particular object inhabits the union. It can be a enum or some other value which tells you the nature of the object.
For example:
struct command{
int *input;
int *output;
int type; // <-- e.g. this value is the union discriminator; 1 => word, 2 => subcommand
union{
char **word;
struct command *subcommand;
} u;
};
Related
the below code provided an O/P :
101:name_provided:name_provided
AFAIK a union can hold only one member at a time, but it looks like both values are visible , is that correct or anything wrong with the code.
#include <stdio.h>
struct test1{
char name[15];
};
struct test2{
char name[15];
};
struct data{
int num;
union{
struct test1 test1_struct;
struct test2 test2_struct;
};
};
int main()
{
struct data data_struct={101,"name_provided"};
printf("\n%d:%s:%s",data_struct.num,data_struct.test1_struct.name,data_struct.test2_struct.name);
return 0;
}
A union specifies that both members will be located at the same place in memory. So if you assign to test1_struct and then read from test2_struct, it will interpret the contents of test1_struct as if it were in the format of test2_struct.
In this case, both structures have the same format, so it doesn't make a difference which one you read and write. It generally makes no sense to use a union where both members are equivalent. The usual purpose of a union is to have different types of members, but not need to have separate memory for each of them, because you only need to use one type at a time. See How can a mixed data type (int, float, char, etc) be stored in an array? for a typical use case.
And see Unions and type-punning for the consequences of accessing a different member than the one you assigned to.
I used a union type in the struct to define whether this person is a student or a staff. When i tried to output the information in the struct array, i found it was hard for me to figure out what kind of this person was ,not to say output the further information. Do not tell me stop using union, sorry, i was asked to do so.
Hers's my simplified data structure:
typedef union student_or_staff{
char *program_name;
char *room_num;
}student_or_staff;
typedef struct people{
char *names;
int age;
student_or_staff s_or_s;
}people[7];
The only way to know what is stored in a union is to include this information in some other place.
There are two common situations that happen when you deal with an array of unions (or structs that hold a union):
All unions in an array hold the same type, or
Each union may hold its own type.
When all unions in an array hold the same type, a single variable that indicates the type the unions hold is sufficient.
When each union could hold a different type, a common approach is to wrap it in a struct, and add a flag indicating which way the union is set. Using your example, the flag should be added to struct people, like this:
enum student_staff_flag {
student_flag
, staff_flag
};
typedef struct people{
char *names;
int age;
enum student_staff_flag s_or_s_flag;
student_or_staff s_or_s;
}people[7];
It is not possible to do this in C but as a workaround you can add a type along your union like this
enum { student_type, staff_type } PEOPLE_TYPE;
typedef union student_or_staff{
char *program_name;
char *room_num;
}student_or_staff;
typedef struct people{
char *names;
int age;
student_or_staff s_or_s;
PEOPLE_TYPE people_type;
}people[7];
Then you just set that along with your union when you assign your struct.
union Data
{
int i;
float f;
char str[20];
} data;
structure Data
{
int i;
float f;
char str[20];
} data;
Here, as I know,"data" is a tag and it is optional. What exactly is it? What advantages can I get by adding a tag while declaring a structure or a union.
Here, as I know,"data" is a tag and it is optional.
No, there is no tag here. A tag indicates which interpretation of a union is correct. For example, if your code assigns data.f and passes data to another function and it reads data.str then you'll have a massive failure in your program that is likely to crash it. The union itself doesn't give the function enough information to know which union member to use.
By adding a tag, you can indicate which interpretation is correct. For example:
struct TaggedData
{
int type;
union Data value;
} taggeddata;
Where type is the tag and indicates what kind of value is stored in the union. A function that reads taggeddata can now use a switch statement and access the correct union member.
Another common name for a tagged data structure is a variant type. Compare to Boost.Variant.
I have the following piece of code:
struct sched_param {
union {
int sched_priority;
struct rcost_sched_param rcost_params;
};
};
I want to know which of the two parameters is "active". Is there a way for me to do that other than adding a int to the struct sched_param?
struct sched_param {
int type;
union {
int sched_priority;
struct rcost_sched_param rcost_params;
};
}
you can add member named type,save the data which parameters is "active"
No, that's the tricky part here: You'll have to store the information which union entry to use (e.g. using a single char member). Also note that both union entries might not necessarily point to the same locations (as you might expect, e.g. due to packing or endianess), so you can't just read one value and determine whether it's containing a valid value or not, since it's up to the compiler how to implement the struct in the union behind the scenes.
Can I check if union is null in c? For example:
union{ char * name, struct Something * something ... }someUnion;
Is there a way to check if no element has been initialized, without doing element vise check?
Thanks.
No, not without adding a specific flag for that purpose. For example:
struct someStruct {
int initialized;
union {
char *name;
struct Something *something;
};
};
You could even store a flag instead of initialized that indicates which kind of data the union contains. This is commonly called a Tagged union.
Yes, under the conditions that all members of the union are of pointer type or a integral type and with initialization you mean a value which is not NULL has been assigned, it is sufficient to check one element for NULL.
union {
char * name;
struct Something * something; } someUnion;
if (someUnion.name != 0) {
// here you know that someUnion.something is not NULL too.
// You don't know if it has been initialized as char*
// or as struct something* though. Presumeably since
// it is a unionboth interpretations make some sense.
}