Purpose of using union within structure in c - c

typedef struct
{
int k;
union
{
int i;
int j;
}use;
}std;
Directly we can use the variable i and j in structure why it is used within union.

In your example, i.e.
typedef struct
{
int k;
union
{
int i;
int j;
}use;
}std;
it doesn't seem to make much sense as i and j are the same type and the names of the variables isn't that descriptive.
It can make sense to have the same type for union elements if that would make the code easier to write, read, understand and maintain. Example:
...
union
{
int numberOfCars;
int numberOfBicycles;
}use;
...
When writing code for handling cars you could use numberOfCars and when writing code for handling bicycles you could use numberOfBicycles. In this way the code would be easier to understand/maintain and the two code blocks could still share a common structure.
In one code block you could have:
std carDealer;
carDealer.use.numberOfCars = 9;
and in another code block (other file perhaps), you could have:
std bicyclesDealer;
bicyclesDealer.use.numberOfBicycles = 9;
A more typical case for unions is that the elements are of different type.

Suppose we wish to store information about employees in an organization.
Name Grade Age
If grade=HSK(Highly skilled)
hobby name
credit card number
If Grade=SSK(Semi skilled)
Vehicle no.
Distance from Company
We can use a single structure for it but then it would lead to wastage of memory coz either hobby name & credit card no. or vehicle no. & distance from com. is used at a time. Both of them are never used simultaneously. So, here union inside structure can be used effectively:
Code:
struct info1
{
char hobby[10];
int crcardno;
};
struct info2
{
char vehno[10];
int dist;
};
union info
{
struct info1 a;
struct info2 b;
};
struct emp
{
char n[20];
char grade[4];
int age;
union info f;
};
struct emp e;
HOPE YOU UNDERSTAND.......
Source : http://cboard.cprogramming.com/c-programming/122228-union-inside-structure.html

Related

How to define struct member as a sum of other members

There are some questions similar to this (namely, Define a struct with a member pointing to anothermember), but, given I'm complete noob at C, I cannot satisfy my doubt reading them, so I'm opening my own in the expectation of having some difference on it (if not, please point me to a proper question and close this as dupe).
What I'm trying to achive is self explanatory:
typedef struct {
int goals_as_visitor;
int goals_as_home;
int total_goals = goals_as_visitor + goals_as_home;
} team
I just want to store the total_goals struct member as permanently being the sum of the other two members. The above code doesn't compile. I don't know if I just haven't found how to do it just yet, or if this is not possible.
Any guidance?
No this is not possible. A C definition is roughly a definition of a storage space, no more. If you want to ensure that the field is always the sum of the first ones, then you need a discipline: each time you modify one of them, you'll have to modify the third. In this regard, OOP languages are better at this, C is too basic. Anyway you can try to use OOP style in C, something like:
typedef struct Team {
int goals_as_visitor;
int goals_as_home;
int total_goals;
} team;
void setGoalAsVisitor(struct Team *this,int value) {
this->goals_as_visitor = value;
this->total_goals = this->goals_as_visitor + this->goals_as_home;
}
...
setGoalAsVisitor(&team,666); // Roughly calling a method on team: aka team.setGoalAsVisitor(666) in Java style
...
and discipline yourself not to use the fields directly.
Note: you can hide many thing to enforce more the discipline, but alas C can let you make nasty things and violate the rules...
Here you are just defining a structures by telling the compiler what members it contains.
To use this structure first you have to declare the structure and then and then only will a memory be allocated for that structure.
Structure members cannot be initialised with declaration.
Definition would be like this:
typedef struct {
int goals_as_visitor;
int goals_as_home;
int total_goals;
} team
and declaration will be like:
team red;
team blue;
Now the structure has some memory allocated, and structure members can be accessed using dot [.] operator.
e.g. red.goals_as_visitor = 10;
Here is a sample code may be this can help you out
#include <stdio.h>
typedef struct {
int goals_as_visitor;
int goals_as_home;
int total_goals;
}team;
int main (void)
{
team red ;
red.goals_as_visitor=10;
red.goals_as_home = 5;
red.total_goals = red.goals_as_visitor + red.goals_as_home;
printf("%d %d %d\n", red.goals_as_visitor, red.goals_as_home, red.total_goals);
return 0;
}
You can refer below link for basics of structures [https://www.geeksforgeeks.org/structures-c/]
It is not possible in c.But the total_goals will always sum of goals_as_visitor and goals_as_home.So the better way is to use total_goals as a function pointer like this
#include<stdio.h>
/*structure and elements*/
struct team;
int tot_g(struct team *sthis);
typedef int (*tot_gol)(struct team *sthis);
struct team
{
int goals_as_visitor;
int goals_as_home;
const tot_gol total_goals;
}
const init={.goals_as_visitor=0,.goals_as_home=0,.total_goals=tot_g};
int tot_g(struct team *sthis)
{
return (sthis->goals_as_visitor+sthis->goals_as_home);
}
typedef struct team team;
/*structure and elements*/
int main()
{
team p=init;
p.goals_as_home=5;
p.goals_as_visitor=5;
printf("%d",p.total_goals(&p));
}
You must always initialize when a team object is defined with init.
Or
The simple way to do this is using a function like
#include<stdio.h>
typedef struct {
int goals_as_visitor;
int goals_as_home;
} team;
int total_goals(team var)
{
return (var.goals_as_home+var.goals_as_visitor);
}
int main()
{
team p;
p.goals_as_home=5;
p.goals_as_visitor=5;
printf("%d",total_goals(p));
}
You can use total_goals function parameter as const pointer also.

Is it possible to choose one of 2 structures dynamically which are under UNION?

This question is regarding C language concepts.
Existing structure:
struct parent{
char c[4];
float f;
double d;
int flag;
struct child_old
{
int i;
float l;
}c1;
}
I want to add a new structure under parent (lets call it - child_new).
I use only one of the child structures at a time based on scenario. Not both at a time.
So I can put them under UNION.
Modified structure:
struct parent{
char c[4];
float f;
double d;
int flag;
union{
struct child_old
{
int i;
float j;
}c1;
struct child_new
{
int i;
float j;
char c[32];
double d;
}c2;
}UU;
}
Here my requirement is, based on struct member "flag" value (0/1), I need to decide which child structure I need to use.
This is because:
There is huge data stored in my file system of type parent structure. There should not be any problem while reading them.
while using child_old, I dont want to consume extra space needed by child_new.
Is it possible in C?
Or is there any work around solution?
What you've written is fine, and you would consume it with something like:
switch(p.flag) {
case CHILD_OLD:
// work with p.c1
break;
case CHILD_NEW:
// work with p.c2
break;
}
However, your full struct will always be big enough for the largest member of the union. So when you use c1, you still have enough space for c2 allocated. But, at least you're not allocating sizeof(c1) + sizeof(c2) each time.
If you really want to allocate more or less space depending on which variant each record uses, you'll need to put a pointer in the struct, and dynamically allocate a separate record for the child elements.
All of this does mean that if you're reading byte arrays from disk then casting them to a struct:
parent *p = (parent*) addressOfSomeDataReadFromAFile;
(Not a great idea, but not unusual in the wild)
... then expanding the parent struct using the union technique will not generally work. Your existing files will represent a record as fewer bytes than the new struct.
Given your requirement of
while using child_old, I dont want to consume extra space needed by child_new.
you can't use a union.
Per 6.7.2.1 Structure and union specifiers, paragraph 16 of the C Standard:
The size of a union is sufficient to contain the largest of its
members.
Thus the size of the union would be that of the largest member.
Note also, as pointed out in the comments, that changing the union may also impact the padding/alignment of other elements of any structure containing that union.
It is possible, but it is neither pretty nor effective. It is considered bad practice to use unions for storing different kinds of unrelated data. And as already mentioned, the size will be that of the biggest member of the union, so it is not memory-efficient either.
Instead, here is a more sensible solution:
struct parent {
char c[4];
float f;
double d;
int flag;
void* data;
}
...
struct parent x;
x.data = malloc(sizeof(struct child_old));
struct child_old* co_ptr = x.data;
co_ptr->i = ...;
Here the void* points at the actual data which is allocated elsewhere. You will also need some means to keep track of which kind of data that is stored there.
It's ugly but it work.
#include <sys/stat.h>
#include <fcntl.h>
enum Type {
A,
B,
};
struct Base {
enum Type type;
};
struct A {
char foo[4];
};
struct B {
char bar[8];
};
struct BaseA {
struct Base base;
struct A a;
};
struct BaseB {
struct Base base;
struct B b;
};
int main(void) {
int fd = open("foo.bar", O_RDONLY);
if (fd == -1) {
return 1;
}
union {
struct Base base;
struct BaseA base_a;
struct BaseB base_b;
} buffer;
if (read(fd, &buffer.base, sizeof buffer.base) != sizeof buffer.base) {
return 1;
}
if (buffer.base.type == A) {
if (read(fd, &buffer.base_a.a, sizeof buffer.base_a.a) !=
sizeof buffer.base_a.a) {
return 1;
}
} else if (buffer.base.type == B) {
if (read(fd, &buffer.base_b.b, sizeof buffer.base_b.b) !=
sizeof buffer.base_b.b) {
return 1;
}
} else {
return 1;
}
}
You could do what you want in if statement. Add every Base_A in an array, and all Base_B in another one.
If you don't want padding use something like #pragma pack(n).

Array of nested structures

I have huge arrays of nested structures which makes it impossible to allot that kind of space and forces me to use heap. But I am facing difficulties using malloc.
The gist of the problem is below.
struct year_of_joining
{
struct district
{
struct colleges
{
struct departments
{
struct sections
{
struct students
{
int sex;
}student[100];
}section_no[8];
}department_no[17];
}college[153];
}dist[13];
};
If I use
int main()
{
int i=0;
struct year_of_joining** year;
year = malloc(100 * sizeof(struct year_of_joining));
for (i = 0; i < 100; i++)
{
year[i] = malloc(sizeof(struct year_of_joining));
}
year[1]->dist[0].college[0].department_no[0].section_no[0].student[8].sex = 1;//works fine
printf("%d", year[1]->dist[0].college[0].department_no[0].section_no[0].student[8].sex);//prints 1
free(year);
return 0;
}
It works fine but when I create a pointer to pointer for dist like year_of_joining and use indirection operator it does not compile:
year[1]->dist[2]->college[0].department_no[0].section_no[0].student[8].sex = 9;//error C2039: 'dist' : is not a member of 'year_of_joining'
How do I solve this? Am I even on the right track?
I think you are way off track here.
Note that a single struct year_of_joining is approximately 100 MiB of data. An array of 100 such structures requires approximately 10 GiB of data (and that is only recording the sex of the students — no other information at all).
struct year_of_joining** year;
year = malloc(100 * sizeof(struct year_of_joining));
This memory allocation allocates enough space for millions of pointers. You almost certainly intended to use:
struct year_of_joining *year = malloc(100 * sizeof(struct year_of_joining));
struct year_of_joining *year = malloc(100 * sizeof(*year));
This allocates 100 years worth of the structure.
However, it seems improbable that you have 13 districts, each of which has exactly 153 colleges, each college having exactly 17 departments, each of which has 8 sections, with each section having exactly 100 students. That corresponds to over 25 million students every year!
You are going to need a vastly more flexible arrangement, where each of the structures contains a pointer to a list of the nested structures, so you can have bigger sections but smaller colleges, etc. It will need to work more along the lines of:
struct students
{
char name[32];
int sex;
// ... and other data ...
};
struct sections
{
char name[32];
// ... and other data ...
int n_students;
struct students *students;
};
struct departments
{
char name[32];
int n_sections;
struct sections *sections;
}
struct colleges
{
char name[32];
// ... and other data ...
int n_departments;
struct departments *departments;
};
struct district
{
char name[32];
// ... and other data ..
int n_colleges;
struct college *colleges;
};
struct year_of_joining
{
int year;
// ... and other data ...
int n_districts;
struct district *districts;
};
Even that feels not entirely correct, but it would be a better way of organizing the data than the original, if only because if a department only has one section and enrolls only ten students (because it is a minority-interest department), then it allocates only enough space for one section and ten students, rather than allocating space for 800 students and 8 sections.
You are not on the right track. Your struct is really huge, and you will need to recompile your program if the size of your input (e.g. number of students) ever gets too big.
I suggest you model your data as smaller structs that can be individually allocated, perhaps using pointers or ID numbers to link them together.
Another language like Ruby might be a better choice than C, allowing you to focus more on your data than on the details of its storage in memory. In general, C is good for fast, low-level interactions with the operating system, while languages with garbage compilers and dynamic typing will be much easier for writing reports and aggregating data.
Anyway, suppose you want to use C. The data structure you choose will depend on several things. What is the precise real-world structure of the data you are modelling? What performance characteristics do you need? Does it need to be fast to add things, or fast to extract certain statistics from the data? Without knowing that answers to these questions, it is hard for us to come up with a usable answer for your application. But Jonathan Leffler has taken a good guess. Here is my guess:
#include <stdint.h>
struct student
{
char * name;
uint32_t sex;
uint32_t year_of_joining;
// Index into an array of sections.
// You could also use a pointer to a section (section *)
// but the pointer would become invalid if you ever moved the
// sections in memory (e.g. by calling realloc on an array
// of sections).
uint32_t section_id;
};
struct section
{
char * name;
uint32_t department_id;
};
struct department
{
char * name;
uint32_t college_id;
};
struct college
{
char * name;
uint32_t district_id;
};
struct district
{
char * name;
};
// These typedefs make it so we don't have to
// write "struct" when using the structs.
typedef struct student student;
typedef struct section section;
typedef struct department department;
typedef struct college college;
typedef struct district district;
// Dynamically sized arrays for holding things.
student * student_array;
section * section_array;
department * department_array;
college * college_array;
district * district_array;

Assigning the value of an union containing structures to NULL in c programming

I have a union and 2 structures in the following format and I need to set one of them to NULL.
For example m = NULL or t = NULL;
typedef struct
{
char *population;
char *area;
} metropolitan;
typedef struct
{
char *airport;
char *type;
} tourist;
typedef union
{
tourist t;
metropolitan m;
} ex;
First of all, the members of your union are not pointers, so it doesn't make all that much sense setting the value to NULL.
Second, the way a union works is that if you set one of the members, you set the others as well. More precisely, all members of a union have the address, but different types. I.e. the different types gives you a way to interpret the same area in memory as multiple types at once.
To differentiate from a strutct:
struct a {
unsigned b;
char *c;
};
In this case, the appropriate number of bytes are allocated for each of the fields a and s, one after the other.
union a {
unsigned b;
char *c;
};
Here, the values of b and c are stored in the same address. I.e. if you're setting a.b to 0, a readout from a.c would give NULL (numeric 0x0).
Since tourist and metropolitan are structs, you cannot assign NULL to them.
But, if you declare like
typedef union
{
tourist* t;
metropolitan* m;
} ex;
you can do
ex e;
e.t=NULL; //which makes e.m=NULL as well
With unions you need to tell them apart.
So define a structure thus:
typedef enum { MET, TOURIST} Chap;
typedef struct {
Chap human;
union {
tourist t;
metropolitan m;
}
} Plonker;
Then you know what is what an then set the appropriate values
i.e
Plonker p;
p.human = MET;
p.m.population = NULL;
... etc

Do I need to create three separate arrays for my assignment?

Ok firstly I'll explain my assignment. For this assignment I have to use dynamic memory allocation which I am having no problems with. What I am having a problem with is figuring out the correct way to work my assignment. For my assignment I need to create a program that prompt the user to enter how many students they have then ask for the following information; Student ID, Birthdate, and Phone number. I need to use a loop to prompt the user to enter all the students information. I need to create a loop that will scan through all the student IDs and find the oldest student using their birthdate (The loop must be able scan through more then 3 students).
Here is my code, I havent done much in it yet because I'm not sure really where to start. I've already setup the dynamic memory allocation, but I don't know how to work the rest of this. Please help me.
Thank you.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int * studentData= NULL;
int students;
printf("How many students are you entering records for:\n");
scanf("%d", &students);
studentData=(int*)malloc((sizeof(int)*students));
}
You could define a structure:
//Define a type, such as int, char, double...
typedef struct studentDataType {
int ID;
int birthDateDay;
int birthDateMonth;
int birthDateYear;
int phoneNumber;
};
Then create an array, where each of those elements is of type studentData:
//Create an array, where each element is of type studentData
studentDataType *studentData = (studentDataType *)malloc(numberOfStudents * sizeof(studentData));
Then loop through them with:
for (int i = 0 ; i < numberOfStudents ; ++i) {
printf("%i %i %i\n", studentData[i].ID, studentData[i].phoneNumber);
}
Use the following struct. You can make year, month and day as separate fields. It will be simpler for a quick start:
struct Student
{
int studentID;
int year;
int month;
int day;
long long phone; // phone is too large for 32 int
};

Resources