C Structures

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 50

C Structures

The structure in C is a user-defined data type that can be used to group items of possibly different
types into a single type. The struct keyword is used to define the structure in the C programming
language. The items in the structure are called its member and they can be of any valid data type.

C Structure Declaration
We have to declare structure in C before using it in our program. In structure declaration, we
specify its member variables along with their datatype. We can use the struct keyword to declare
the structure in C using the following syntax:

Syntax

struct structure_name {
data_type member_name1; data_type member_name1;

....
....
};
The above syntax is also called a structure template or structure prototype and no memory is
allocated to the structure in the declaration.

C Structure Definition
To use structure in our program, we have to define its instance. We can do that by creating
variables of the structure type. We can define structure variables using two methods:

1. Structure Variable Declaration with Structure Template

struct structure_name {
data_type member_name1;
data_type member_name1;
....
....
}variable1, varaible2, ...;

2. Structure Variable Declaration after Structure Template

// structure declared beforehandstruct structure_name variable1, variable2 , .......;

Access Structure Members


We can access structure members by using the ( . ) dot operator.

Syntax

structure_name.member1;
strcuture_name.member2;
In the case where we have a pointer to the structure, we can also use the arrow operator to access
the members.

Initialize Structure Members


Structure members cannot be initialized with the declaration. For example, the following C program
fails in the compilation.

struct Point
{
int x = 0; // COMPILER ERROR: cannot initialize members here
int y = 0; // COMPILER ERROR: cannot initialize members here
};
The reason for the above error is simple. When a datatype is declared, no memory is allocated for it.
Memory is allocated only when variables are created.

We can initialize structure members in 3 ways which are as follows:

1. Using Assignment Operator.


2. Using Initializer List.
3. Using Designated Initializer List.

1. Initialization using Assignment Operator

struct structure_name str;


str.member1 = value1;
str.member2 = value2;
str.member3 = value3;
.
.
.

2. Initialization using Initializer List


struct structure_name str = { value1, value2, value3 };
In this type of initialization, the values are assigned in sequential order as they are declared in the
structure template.

3. Initialization using Designated Initializer List

Designated Initialization allows structure members to be initialized in any order. This feature has
been added in the C99 standard.

struct structure_name str = { .member1 = value1, .member2 = value2, .member3 =


value3 };
The Designated Initialization is only supported in C but not in C++.

Example of Structure in C
The following C program shows how to use structures

// C program to illustrate the use of structures


#include <stdio.h>

// declaring structure with name str1


struct str1 {
int i;
char c;
float f;
char s[30];
};

// declaring structure with name str2


struct str2 {
int ii;
char cc;
float ff;
} var; // variable declaration with structure
template

// Driver code
int main()
{
// variable declaration after structure
template
// initialization with initializer list and
designated
// initializer list
struct str1 var1 = { 1, 'A', 1.00,
"GeeksforGeeks" },
var2;
struct str2 var3 = { .ff = 5.00, .ii = 5, .cc
= 'a' };

// copying structure using assignment


operator
var2 = var1;

printf("Struct 1:\n\ti = %d, c = %c, f = %f,


s = %s\n",
var1.i, var1.c, var1.f, var1.s);
printf("Struct 2:\n\ti = %d, c = %c, f = %f,
s = %s\n",
var2.i, var2.c, var2.f, var2.s);
printf("Struct 3\n\ti = %d, c = %c, f
= %f\n", var3.ii,
var3.cc, var3.ff);

return 0;
}

Output
Struct 1:
i = 1, c = A, f = 1.000000, s = GeeksforGeeks
Struct 2:
i = 1, c = A, f = 1.000000, s = GeeksforGeeks
Struct 3
i = 5, c = a, f = 5.000000

typedef for Structures


The typedef keyword is used to define an alias for the already existing datatype. In structures, we
have to use the struct keyword along with the structure name to define the variables. Sometimes,
this increases the length and complexity of the code. We can use the typedef to define some new
shorter name for the structure.

Example

// C Program to illustrate the use of


typedef with
// structures
#include <stdio.h>

// defining structure
struct str1 {
int a;
};

// defining new name for str1


typedef struct str1 str1;

// another way of using typedef with


structures
typedef struct str2 {
int x;
} str2;

int main()
{
// creating structure variables using
new names
str1 var1 = { 20 };
str2 var2 = { 314 };

printf("var1.a = %d\n", var1.a);


printf("var2.x = %d", var2.x);

return 0;
}

Output
var1.a = 20
var2.x = 314

Nested Structures
C language allows us to insert one structure into another as a member. This process is called nesting
and such structures are called nested structures. There are two ways in which we can nest one
structure into another:

1. Embedded Structure Nesting

In this method, the structure being nested is also declared inside the parent structure.

Example

struct parent {
int member1;
struct member_str member2 {
int member_str1;
char member_str2;
...
}
...
}

2. Separate Structure Nesting

In this method, two structures are declared separately and then the member structure is nested
inside the parent structure.

Example

struct member_str {
int member_str1;
char member_str2;
...
}

struct parent {
int member1;
struct member_str member2;
...
}
One thing to note here is that the declaration of the structure should always be present before its
definition as a structure member. For example, the declaration below is invalid as the struct mem is
not defined when it is declared inside the parent structure.

struct parent {
struct mem a;
};

struct mem {
int var;
};

Accessing Nested Members

We can access nested Members by using the same ( . ) dot operator two times as shown:

str_parent.str_child .member;

Example of Structure Nesting

// C Program to illustrate structure nesting


along with
// forward declaration
#include <stdio.h>

// child structure declaration


struct child {
int x;
char c;
};

// parent structure declaration


struct parent {
int a;
struct child b;
};

// driver code
int main()
{
struct parent var1 = { 25, 195, 'A' };

// accessing and printing nested members


printf("var1.a = %d\n", var1.a);
printf("var1.b.x = %d\n", var1.b.x);
printf("var1.b.c = %c", var1.b.c);
return 0;
}

Output
var1.a = 25
var1.b.x = 195
var1.b.c = A

Structure Pointer in C
We can define a pointer that points to the structure like any other variable. Such pointers are
generally called Structure Pointers. We can access the members of the structure pointed by the
structure pointer using the ( -> ) arrow operator.

Example of Structure Pointer

// C program to illustrate the structure pointer


#include <stdio.h>

// structure declaration
struct Point {
int x, y;
};

int main()
{
struct Point str = { 1, 2 };

// p2 is a pointer to structure p1
struct Point* ptr = &str;

// Accessing structure members using


structure pointer
printf("%d %d", ptr->x, ptr->y);

return 0;
}

Output
1 2

Self-Referential Structures
The self-referential structures in C are those structures that contain references to the same type as
themselves i.e. they contain a member of the type pointer pointing to the same structure type.

Example of Self-Referential Structures

struct structure_name {
data_type member1; data_type member2; struct structure_name* str;

}
// C program to illustrate the self referential
structures
#include <stdio.h>

// structure template
typedef struct str {
int mem1;
int mem2;
struct str* next;
}str;

// driver code
int main()
{
str var1 = { 1, 2, NULL };
str var2 = { 10, 20, NULL };

// assigning the address of var2 to var1.next


var1.next = &var2;

// pointer to var1
str *ptr1 = &var1;

// accessing var2 members using var1


printf("var2.mem1: %d\nvar2.mem2: %d", ptr1-
>next->mem1,
ptr1->next->mem2);

return 0;
}

Output
var2.mem1: 10
var2.mem2: 20
Such kinds of structures are used in different data structures such as to define the nodes of linked
lists, trees, etc.

C Structure Padding and Packing


Technically, the size of the structure in C should be the sum of the sizes of its members. But it may
not be true for most cases. The reason for this is Structure Padding.

Structure padding is the concept of adding multiple empty bytes in the structure to naturally align
the data members in the memory. It is done to minimize the CPU read cycles to retrieve different
data members in the structure.

There are some situations where we need to pack the structure tightly by removing the empty bytes.
In such cases, we use Structure Packing. C language provides two ways for structure packing:

1. Using #pragma pack(1)


2. Using __attribute((packed))__

Example of Structure Padding and Packing


// C program to illustrate structure padding
and packing
#include <stdio.h>

// structure with padding


struct str1 {
char c;
int i;
};

struct str2 {
char c;
int i;
} __attribute((packed)) __; // using structure
packing

// driver code
int main()
{

printf("Size of str1: %d\n", sizeof(struct


str1));
printf("Size of str2: %d\n", sizeof(struct
str2));
return 0;
}

Output
Size of str1: 8
Size of str2: 5
As we can see, the size of the structure is varied when structure packing is performed.

To know more about structure padding and packing, refer to this article – Structure Member
Alignment, Padding and Data Packing.

Bit Fields
Bit Fields are used to specify the length of the structure members in bits. When we know the
maximum length of the member, we can use bit fields to specify the size and reduce memory
consumption.

Syntax of Bit Fields

struct structure_name {
data_type member_name: width_of_bit-field;

};

Example of Bit Fields

// C Program to illustrate bit fields in


structures
#include <stdio.h>
// declaring structure for reference
struct str1 {
int a;
char c;
};

// structure with bit fields


struct str2 {
int a : 24; // size of 'a' is 3 bytes =
24 bits
char c;
};

// driver code
int main()
{
printf("Size of Str1: %d\nSize of
Str2: %d",
sizeof(struct str1),
sizeof(struct str2));
return 0;
}

Output
Size of Str1: 8
Size of Str2: 4
As we can see, the size of the structure is reduced when using the bit field to define the max size of
the member ‘a’.

Uses of Structure in C
C structures are used for the following:

1. The structure can be used to define the custom data types that can be used to create some
complex data types such as dates, time, complex numbers, etc. which are not present in the
language.
2. It can also be used in data organization where a large amount of data can be stored in
different fields.
3. Structures are used to create data structures such as trees, linked lists, etc.
4. They can also be used for returning multiple values from a function.

Limitations of C Structures
In C language, structures provide a method for packing together data of different types. A
Structure is a helpful tool to handle a group of logically related data items. However, C structures
also have some limitations.

 Higher Memory Consumption: It is due to structure padding.


 No Data Hiding: C Structures do not permit data hiding. Structure members can be accessed
by any function, anywhere in the scope of the structure.
 Functions inside Structure: C structures do not permit functions inside the structure so we
cannot provide the associated functions.
 Static Members: C Structure cannot have static members inside its body.
 Construction creation in Structure: Structures in C cannot have a constructor inside
Structures.

Related Articles

 C Structures vs C++ Structure

dot (.) Operator in C


The C dot (.) operator is used for direct member selection via the name of variables of type struct
and union. Also known as the direct member access operator, it is a binary operator that helps us
to extract the value of members of the structures and unions.

Syntax of Dot Operator

variable_name.member;
 variable_name: An instance of a structure or a union.
 member: member associated with the created structure or union.

Example of dot(.) Operator

// C program to demonstrate the use of dot


operator
#include <stdio.h>

struct str {
int mem;
};

union un {
int mem1;
char mem2;
};

int main()
{
struct str str_name = { 12};
union un un_name;

// accessing union member


un_name.mem1 = 9;
printf("Union Member 1: %d\n",
un_name.mem1);

// accessing structure member


printf("Structure Member: %d",
str_name.mem);

return 0;
}

Output
Union Member 1: 9
Structure Member: 12

dot(.) operator with Nested Structures and Unions


The dot operator can also be used to access the members of nested structures and unions. It can be
done in the same way as done for the normal structure.

Syntax with Nested Struct

variable_name.member1.member2;
Example:

// C program to illustrate the use of dot operator


for
// nested structure
#include <stdio.h>

struct base {
struct child {
int i;
} child;
};

int main()
{
struct base s_name = { 12 };

// accessing nested structure member using


dot operator
printf("Nested Structure Variable: %d",
s_name.child.i);
return 0;
}

Output
Nested Structure Variable: 12

Operator Precedence of dot (.) Operator


The dot (.) operator has the highest operator precedence in C Language and its associativity is from
left to right. To know more about operator precedence, please refer to the Operator Precedence in
C.

Note: dot (.) operator can only be used with structure or unions in C language.
C typedef
The typedef is a keyword that is used to provide existing data types with a new name. The C
typedef keyword is used to redefine the name of already existing data types.

When names of datatypes become difficult to use in programs, typedef is used with user-defined
datatypes, which behave similarly to defining an alias for commands.

C typedef Syntax
typedef existing_name alias_name;

After this declaration, we can use the alias_name as if it were the real existing_name in out C
program.

Example of typedef in C
typedef long long ll;
Below is the C program to illustrate how to use typedef.

 C

// C program to implement typedef


#include <stdio.h>

// defining an alias using typedef


typedef long long ll;

// Driver code
int main()
{
// using typedef name to declare
variable
ll var = 20;
printf("%ld", var);

return 0;
}

Output
20

Use of typedef in C
Following are some common uses of the typedef in C programming:

 The typedef keyword gives a meaningful name to the existing data type which helps other
users to understand the program more easily.
 It can be used with structures to increase code readability and we don’t have to type struct
repeatedly.
 The typedef keyword can also be used with pointers to declare multiple pointers in a single
statement.
 It can be used with arrays to declare any number of variables.

1. typedef struct
typedef can also be used with structures in the C programming language. A new data type can be
created and used to define the structure variable.

Example 1: Using typedef to define a name for a structure

// C program to implement
// typedef with structures
#include <stdio.h>
#include <string.h>

// using typedef to define an alias for


structure
typedef struct students {
char name[50];
char branch[50];
int ID_no;
} stu;

// Driver code
int main()
{
stu st;
strcpy(st.name, "Kamlesh Joshi");
strcpy(st.branch, "Computer Science And
Engineering");
st.ID_no = 108;

printf("Name: %s\n", st.name);


printf("Branch: %s\n", st.branch);
printf("ID_no: %d\n", st.ID_no);
return 0;
}

Output
Name: Kamlesh Joshi
Branch: Computer Science And Engineering
ID_no: 108

2. typedef with Pointers


typedef can also be used with pointers as it gives an alias name to the pointers. Typedef is very
efficient while declaring multiple pointers in a single statement because pointers bind to the right on
the simple declaration.

Example:

typedef int* Int_ptr;


Int_ptr var, var1, var2;
In the above statement var, var1, and var2 are declared as pointers of type int which helps us to
declare multiple numbers of pointers in a single statement.

Example 2: Using typedef to define a name for pointer type.


// C program to implement
// typedef with pointers
#include <stdio.h>

typedef int* ptr;

// Driver code
int main()
{
ptr var;
*var = 20;

printf("Value of var is %d",


*var);
return 0;
}

Output
Value of var is 20

3. typedef with Array


typedef can also be used with an array to increase their count.

Example:

typedef int arr[20]


Here, arr is an alias for an array of 20 integer elements.

// it's same as Arr[20], two-Arr[20][23];


arr Arr, two-Arr[23];

Example 3: Using typedef to define an alias for Array.

// C program to implement typedef


with array
#include <stdio.h>

typedef int Arr[4];

// Driver code
int main()
{
Arr temp = { 10, 20, 30, 40 };
printf("typedef using an
array\n");

for (int i = 0; i < 4; i++) {


printf("%d ", temp[i]);
}
return 0;
}

Output
typedef using an array
10 20 30 40
C typedef vs #define
The following are the major difference between the typedef and #define in C:

1. #define is capable of defining aliases for values as well, for instance, you can define 1 as ONE,
3.14 as PI, etc. Typedef is limited to giving symbolic names to types only.
2. Preprocessors interpret #define statements, while the compiler interprets typedef statements.
3. There should be no semicolon at the end of #define, but a semicolon at the end of typedef.
4. In contrast with #define, typedef will actually define a new type by copying and pasting the
definition values.
Below is the C program to implement #define:

// C program to implement
#define
#include <stdio.h>

// macro definition
#define LIMIT 3

// Driver code
int main()
{
for (int i = 0; i < LIMIT;
i++) {
printf("%d \n", i);
}
return 0;
}

Output
0
1
2

FAQs on typedef in C

1. What is typedef in C?

The C typedef statement defines an alias or a nickname for the already existing data type.

2. What is typedef struct?

The typedef struct is the statement used to define an alias for the structure data type.

3. What is typedef enum?

The typedef enum is used to define the alias for the enumeration data type.
Structure Member Alignment, Padding and Data Packing
In C, the structures are used as data packs. They don’t provide any data encapsulation or data
hiding features.

In this article, we will discuss the property of structure padding in C along with data alignment and
structure packing.

Data Alignment in Memory


Every data type in C will have alignment requirements (in fact it is mandated by processor
architecture, not by language). A processor will have processing word length as that of data bus size.
On a 32-bit machine, the processing word size will be 4 bytes.

Historically memory is byte addressable and arranged sequentially. If the memory is arranged as a
single bank of one-byte width, the processor needs to issue 4 memory read cycles to fetch an
integer. It is more economical to read all 4 bytes of an integer in one memory cycle. To take such
advantage, the memory will be arranged as a group of 4 banks as shown in the above figure.

The memory addressing still be sequential. If bank 0 occupies an address X, bank 1, bank 2 and
bank 3 will be at (X + 1), (X + 2), and (X + 3) addresses. If an integer of 4 bytes is allocated on X
address (X is a multiple of 4), the processor needs only one memory cycle to read the entire integer.
Whereas, if the integer is allocated at an address other than a multiple of 4, it spans across two
rows of the banks as shown in the below figure. Such an integer requires two memory read cycles to
fetch the data.

A variable’s data alignment deals with the way the data is stored in these banks. For example, the
natural alignment of int on a 32-bit machine is 4 bytes. When a data type is naturally aligned, the
CPU fetches it in minimum read cycles.
Similarly, the natural alignment of a short int is 2 bytes. It means a short int can be stored in bank
0 – bank 1 pair or bank 2 – bank 3 pair. A double requires 8 bytes and occupies two rows in the
memory banks. Any misalignment of double will force more than two read cycles to
fetch double data.

Note that a double variable will be allocated on an 8-byte boundary on a 32-bit machine and
requires two memory read cycles. On a 64-bit machine, based on a number of banks,
a double variable will be allocated on the 8-byte boundary and requires only one memory read cycle.

Structure Padding in C
Structure padding is the addition of some empty bytes of memory in the structure to naturally
align the data members in the memory. It is done to minimize the CPU read cycles to retrieve
different data members in the structure.

Try to calculate the size of the following structures:

// structure A
typedef struct
structa_tag {
char c;
short int s;
} structa_t;

// structure B
typedef struct
structb_tag {
short int s;
char c;
int i;
} structb_t;

// structure C
typedef struct
structc_tag {
char c;
double d;
int s;
} structc_t;

// structure D
typedef struct
structd_tag {
double d;
int s;
char c;
} structd_t;

Calculating the size of each structure by directly adding the size of all the members, we get:

 Size of Structure A = Size of (char + short int) = 1 + 2 = 3.


 Size of Structure B = Size of (short int + char + int) = 2 + 1 + 4 = 7.
 Size of Structure C = Size of (char + double + int) = 1 + 8 + 4 = 13.
 Size of Structure A = Size of (double + int + char) = 8 + 4 + 1= 13.
Now let’s confirm the size of these structures using the given C Program:
// C Program to demonstrate the structure padding
property
#include <stdio.h>

// Alignment requirements
// (typical 32 bit machine)

// char 1 byte
// short int 2 bytes
// int 4 bytes
// double 8 bytes

// structure A
typedef struct structa_tag {
char c;
short int s;
} structa_t;

// structure B
typedef struct structb_tag {
short int s;
char c;
int i;
} structb_t;

// structure C
typedef struct structc_tag {
char c;
double d;
int s;
} structc_t;

// structure D
typedef struct structd_tag {
double d;
int s;
char c;
} structd_t;

int main()
{
printf("sizeof(structa_t) = %lu\n",
sizeof(structa_t));
printf("sizeof(structb_t) = %lu\n",
sizeof(structb_t));
printf("sizeof(structc_t) = %lu\n",
sizeof(structc_t));
printf("sizeof(structd_t) = %lu\n",
sizeof(structd_t));

return 0;
}

Output
sizeof(structa_t) = 4
sizeof(structb_t) = 8
sizeof(structc_t) = 24
sizeof(structd_t) = 16
As we can see, the size of the structures is different from those we calculated.

This is because of the alignment requirements of various data types, every member of
the structure should be naturally aligned. The members of the structure are allocated
sequentially in increasing order.

Let us analyze each struct declared in the above program. For the sake of convenience, assume every
structure type variable is allocated on a 4-byte boundary (say 0x0000), i.e. the base address of the
structure is multiple of 4 (need not necessarily always, see an explanation of structc_t).

Structure A
The structa_t first element is char which is one byte aligned, followed by short int. short int is 2
bytes aligned. If the short int element is immediately allocated after the char element, it will start
at an odd address boundary. The compiler will insert a padding byte after the char to ensure short
int will have an address multiple of 2 (i.e. 2 byte aligned). The total size of structa_t will be,
sizeof(char) + 1 (padding) + sizeof(short), 1 + 1 + 2 = 4 bytes.

Structure B
The first member of structb_t is short int followed by char. Since char can be on any byte boundary
no padding is required between short int and char, in total, they occupy 3 bytes. The next member
is int. If the int is allocated immediately, it will start at an odd byte boundary. We need 1-byte
padding after the char member to make the address of the next int member 4-byte aligned. On
total,

the structb_t requires , 2 + 1 + 1 (padding) + 4 = 8 bytes.

Structure C – Every structure will also have alignment requirements


Applying same analysis, structc_t needs sizeof(char) + 7-byte padding + sizeof(double) + sizeof(int) =
1 + 7 + 8 + 4 = 20 bytes. However, the sizeof(structc_t) is 24 bytes. It is because, along with
structure members, structure type variables will also have natural alignment. Let us understand it
by an example. Say, we declared an array of structc_t as shown below

structc_t structc_array[3];
Assume, the base address of structc_array is 0x0000 for easy calculations. If the structc_t occupies
20 (0x14) bytes as we calculated, the second structc_t array element (indexed at 1) will be at
0x0000 + 0x0014 = 0x0014. It is the start address of the index 1 element of the array. The
double member of this structc_t will be allocated on 0x0014 + 0x1 + 0x7 = 0x001C (decimal 28)
which is not multiple of 8 and conflicts with the alignment requirements of double. As we
mentioned at the top, the alignment requirement of double is 8 bytes.

In order to avoid such misalignment, the compiler introduces alignment requirements to every
structure. It will be as that of the largest member of the structure. In our case alignment of
structa_t is 2, structb_t is 4 and structc_t is 8. If we need nested structures, the size of the largest
inner structure will be the alignment of an immediate larger structure.

In structc_t of the above program, there will be a padding of 4 bytes after the int member to make
the structure size multiple of its alignment. Thus the size of (structc_t) is 24 bytes. It guarantees
correct alignment even in arrays.
Structure D
In a similar way, the size of the structure D is :

sizeof(double) + sizeof(int) + sizeof(char) + padding(3) = 8 + 4 + 1 + 3 = 16


bytes

How to Reduce Structure Padding?

By now, it may be clear that padding is unavoidable. There is a way to minimize padding. The
programmer should declare the structure members in their increasing/decreasing order of size. An
example is structd_t given in our code, whose size is 16 bytes in lieu of 24 bytes of structc_t.

What is Structure Packing?


Sometimes it is mandatory to avoid padded bytes among the members of the structure. For
example, reading contents of ELF file header or BMP or JPEG file header. We need to define a
structure similar to that of the header layout and map it. However, care should be exercised in
accessing such members. Typically reading byte by byte is an option to avoid misaligned exceptions
but there will be a hit on performance.

Most of the compilers provide nonstandard extensions to switch off the default padding like
pragmas or command line switches. Consult the documentation of the respective compiler for more
details.

In GCC, we can use the following code for structure packing:


#pragma pack(1)

or

struct name {
...
}__attribute__((packed)) ;

Example of Structure Packing

// C Program to demonstrate the structure packing


#include <stdio.h>
#pragma pack(1)

// structure A
typedef struct structa_tag {
char c;
short int s;
} structa_t;

// structure B
typedef struct structb_tag {
short int s;
char c;
int i;
} structb_t;

// structure C
typedef struct structc_tag {
char c;
double d;
int s;
} structc_t;

// structure D
typedef struct structd_tag {
double d;
int s;
char c;
} structd_t;

int main()
{
printf("sizeof(structa_t) = %lu\n",
sizeof(structa_t));
printf("sizeof(structb_t) = %lu\n",
sizeof(structb_t));
printf("sizeof(structc_t) = %lu\n",
sizeof(structc_t));
printf("sizeof(structd_t) = %lu\n",
sizeof(structd_t));

return 0;
}

Output
sizeof(structa_t) = 3
sizeof(structb_t) = 7
sizeof(structc_t) = 13
sizeof(structd_t) = 13

FAQs on Structure Padding in C

1. Is alignment applied for stack?

Yes. The stack is also memory. The system programmer should load the stack pointer with a
memory address that is properly aligned. Generally, the processor won’t check stack alignment, it is
the programmer’s responsibility to ensure proper alignment of stack memory. Any misalignment
will cause run-time surprises.
For example, if the processor word length is 32-bit, the stack pointer also should be aligned to be a
multiple of 4 bytes.

2. If char data is placed in a bank other than bank 0, it will be placed on the wrong data
lines during memory reading. How the processor handles char type?

Usually, the processor will recognize the data type based on instruction (e.g. LDRB on an ARM
processor). Depending on the bank it is stored, the processor shifts the byte onto the least significant
data lines.
3. When arguments are passed on the stack, are they subjected to alignment?

Yes. The compiler helps the programmer in making proper alignment. For example, if a 16-bit
value is pushed onto a 32-bit wide stack, the value is automatically padded with zeros out to 32
bits. Consider the following program.

void argument_alignment_check( char c1, char


c2 )
{
// Considering downward stack
// (on upward stack the output will be
negative)
printf("Displacement %d\n", (int)&c2 -
(int)&c1);
}

The output will be 4 on a 32-bit machine. It is because each character occupies 4 bytes due to
alignment requirements.

4. What will happen if we try to access misaligned data?

It depends on the processor architecture. If the access is misaligned, the processor automatically
issues sufficient memory read cycles and packs the data properly onto the data bus. The penalty is
on performance. Whereas few processors will not have the last two address lines, which means there
is no way to access the odd byte boundary. Every data access must be aligned (4 bytes) properly.
Misaligned access is a critical exception on such processors. If the exception is ignored, read data will
be incorrect and hence the results.

5. Is there any way to query the alignment requirements of a data type?

Yes. Compilers provide non-standard extensions for such needs. For example, __alignof() in Visual
Studio helps in getting the alignment requirements of data type. Read MSDN for details.

6. When memory reading is efficient in reading 4 bytes at a time on a 32-bit machine,


why should a double type be aligned on an 8-byte boundary?

It is important to note that most of the processors will have a math co-processor, called Floating
Point Unit (FPU). Any floating point operation in the code will be translated into FPU instructions.
The main processor is nothing to do with floating-point execution. All this will be done behind the
scenes.

As per standard, the double type will occupy 8 bytes. And, every floating point operation performed
in FPU will be of 64-bit length. Even float types will be promoted to 64 bits prior to execution.

The 64-bit length of FPU registers forces double type to be allocated on an 8-byte boundary. I am
assuming (I don’t have concrete information) in the case of FPU operations, data fetch might be
different, I mean the data bus since it goes to FPU. Hence, the address decoding will be different for
double types (which are expected to be on an 8-byte boundary). It means the address decoding
circuits of the floating point unit will not have the last 3 pins.

This article is contributed by Venki. Please write comments if you find anything incorrect, or if you
want to share more information about the topic discussed above.

Flexible Array Members in a structure in C


Flexible Array Member(FAM) is a feature introduced in the C99 standard of the C programming
language.

 For the structures in C programming language from C99 standard onwards, we can declare
an array without a dimension and whose size is flexible in nature.
 Such an array inside the structure should preferably be declared as the last member of the
structure and its size is variable(can be changed at runtime).
 The structure must contain at least one more named member in addition to the flexible
array member.
What must be the size of the structure below?

struct student {
int stud_id;
int name_len;
int
struct_size;
char
stud_name[];
};

The size of structure is = 4 + 4 + 4 + 0 = 12


In the above code snippet, the size i.e. length of array “stud_name” isn’t fixed and is a FAM.
The memory allocation using flexible array members(as per C99 standards) for the above example
can be done as:

struct student *s = malloc( sizeof(*s) + sizeof(char [strlen(stud_name)]) );


Note: While using flexible array members in structures some convention regarding the
actual size of the member is defined. The convention is that the flexible array member
does not contribute to the size of the structure itself. Instead, the size of the structure
is determined by the other data members plus any memory allocated dynamically for
the flexible array.

In the above example, the convention is that the member “stud_name” has a size of the number of
characters stored.

For Example, Consider the following structure:

Input : id = 15, name = "Kartik" Output : Student_id : 15


Stud_Name : Kartik
Name_Length: 6
Allocated_Struct_size: 18
Memory allocation of the above structure:

struct student *s =
malloc( sizeof(*s) + sizeof(char [strlen("Kartik")]));
Its structure representation is equal to:

struct student {
int stud_id;
int name_len;
int struct_size;
char stud_name[6]; // character array of
length 6
};

Example

The below C program shows the implementation of flexible array members.

// C program for variable length members in


// structures in GCC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// A structure of type student


struct student {
int stud_id;
int name_len;

// This is used to store size of flexible


// character array stud_name[]
int struct_size;

// Flexible Array Member(FAM)


// variable length array must be last
// member of structure
char stud_name[];
};

// Memory allocation and initialisation of


structure
struct student* createStudent(struct student* s,
int id,
char a[])
{
// Allocating memory according to user
provided
// array of characters
s = malloc(sizeof(*s) + sizeof(char) *
strlen(a));

s->stud_id = id;
s->name_len = strlen(a);
strcpy(s->stud_name, a);
// Assigning size according to size of
stud_name
// which is a copy of user provided array
a[].
s->struct_size
= (sizeof(*s)
+ sizeof(char) * strlen(s-
>stud_name));

return s;
}

// Print student details


void printStudent(struct student* s)
{
printf("Student_id : %d\n"
"Stud_Name : %s\n"
"Name_Length: %d\n"
"Allocated_Struct_size: %d\n\n",
s->stud_id, s->stud_name, s-
>name_len,
s->struct_size);

// Value of Allocated_Struct_size is in
bytes here
}

// Driver Code
int main()
{
struct student* s1 = createStudent(s1, 523,
"Cherry");
struct student* s2
= createStudent(s2, 535,
"Sanjayulsha");

printStudent(s1);
printStudent(s2);

// Size in struct student


printf("Size of Struct student: %lu\n",
sizeof(struct student));

// Size in struct pointer


printf("Size of Struct pointer: %lu",
sizeof(s1));

return 0;
}

Output

Student_id : 523
Stud_Name : SanjayKanna
Name_Length: 11
Allocated_Struct_size: 23
Student_id : 535
Stud_Name : Cherry
Name_Length: 6
Allocated_Struct_size: 18

Size of Struct student: 12


Size of Struct pointer: 8

Important Points

1. Adjacent memory locations are used to store structure members in memory.


2. In previous standards of the C programming language, we were able to declare a zero-size
array member in place of a flexible array member. The GCC compiler with C89 standard
considers it as zero size array.

C Unions
The Union is a user-defined data type in C language that can contain elements of the different data
types just like structure. But unlike structures, all the members in the C union are stored in the
same memory location. Due to this, only one member can store data at the given instance.

Syntax of Union in C
The syntax of the union in C can be divided into three steps which are as follows:

C Union Declaration

In this part, we only declare the template of the union, i.e., we only declare the members’ names
and data types along with the name of the union. No memory is allocated to the union in the
declaration.

union union_name {
datatype member1 ;

datatype member2 ;

...
};
Keep in mind that we have to always end the union declaration with a semi-colon.
Different Ways to Define a Union Variable

We need to define a variable of the union type to start using union members. There are two
methods using which we can define a union variable.

1. With Union Declaration


2. After Union Declaration
1. Defining Union Variable with Declaration
union union_name {
datatype member1;
datatype member2;
...
} var1, var2, ...;
2. Defining Union Variable after Declaration
union union_name var1, var2, var3 ...;

where union_name is the name of an already declared union.

Access Union Members

We can access the members of a union by using the ( . ) dot operator just like structures.

var1.member1 ;

where var1 is the union variable and member1 is the member of the union.

The above method of accessing the members of the union also works for the nested unions.
var1.member1.memberA;

Here,

 var1 is a union variable.


 member1 is a member of the union.
 memberA is a member of member1.

Initialization of Union in C

The initialization of a union is the initialization of its members by simply assigning the value to it.

var1.member1 = some_value ;

One important thing to note here is that only one member can contain some value at a given
instance of time.

Example of Union
// C Program to demonstrate how to use
union
#include <stdio.h>

// union template or declaration


union un {
int member1;
char member2;
float member3;
};

// driver code
int main()
{

// defining a union variable


union un var1;

// initializing the union member


var1.member1 = 15;

printf("The value stored in


member1 = %d",
var1.member1);

return 0;
}

Output
The value stored in member1 = 15

Size of Union
The size of the union will always be equal to the size of the largest member of the array. All the
less-sized elements can store the data in the same space without any overflow.

Memory Allocation in C Union

Example 1: C program to find the size of the union

// C Program to find the size of


the union
#include <stdio.h>

// declaring multiple unions


union test1 {
int x;
int y;
} Test1;

union test2 {
int x;
char y;
} Test2;

union test3 {
int arr[10];
char y;
} Test3;

// driver code
int main()
{
// finding size using sizeof()
operator
int size1 = sizeof(Test1);
int size2 = sizeof(Test2);
int size3 = sizeof(Test3);

printf("Sizeof test1: %d\n",


size1);
printf("Sizeof test2: %d\n",
size2);
printf("Sizeof test3: %d",
size3);
return 0;
}

Output
Sizeof test1: 4
Sizeof test2: 4
Sizeof test3: 40

Difference between C Structure and C Union


The following table lists the key difference between the structure and union in C:

Structure Union

The size of the structure is equal to or greater The size of the union is the
than the total size of all of its members. size of its largest member.

The structure can contain data in multiple Only one member can contain
members at the same time. data at the same time.

It is declared using the union


It is declared using the struct keyword.
keyword.

FAQs on C Unions

1. What is the size of the given union?

union un {
int a;
int arr[20];
}
Ans: The size of the given union is 20 x 4 bytes = 80 bytes. Even if the array is a collection of
similar data elements, it is considered to be a single entity by the C compiler.

2. Can we store data in multiple union members at the same time?

No. We can only store data in a single member at the same time. For example in the following C
program, both x and y share the same location. If we change x, we can see the changes being
reflected in y.

// C program to check if we can store data in


multiple union
// members
#include <stdio.h>

// Declaration of union is same as structures


union test {
int x, y;
};

int main()
{
// A union variable t
union test t;

t.x = 2; // t.y also gets value 2


printf("After making x = 2:\n x = %d, y
= %d\n\n", t.x,
t.y);

t.y = 10; // t.x is also updated to 10


printf("After making y = 10:\n x = %d, y
= %d\n\n", t.x,
t.y);
return 0;
}

Output
After making x = 2:
x = 2, y = 2

After making y = 10:


x = 10, y = 10

3. What are the applications of unions?

Unions can be useful in many situations where we want to use the same memory for two or more
members. For example, suppose we want to implement a binary tree data structure where each leaf
node has a double data value, while each internal node has pointers to two children, but no data. If
we declare this as:
struct NODE {
struct NODE*
left;
struct NODE*
right;
double data;
};

then every node requires 16 bytes, with half the bytes wasted for each type of node. On the other
hand, if we declare a node as the following, then we can save space.

struct NODE {
bool is_leaf;
union {
struct {
struct NODE*
left;
struct NODE*
right;
} internal;
double data;
} info;
};

Bit Fields in C
In C, we can specify the size (in bits) of the structure and union members. The idea of bit-field is to
use memory efficiently when we know that the value of a field or group of fields will never exceed a
limit or is within a small range. C Bit fields are used when the storage of our program is limited.

Need of Bit Fields in C

 Reduces memory consumption.


 To make our program more efficient and flexible.
 Easy to Implement.

Declaration of C Bit Fields


Bit-fields are variables that are defined using a predefined width or size. Format and the
declaration of the bit-fields in C are shown below:

Syntax of C Bit Fields

struct
{
data_type member_name : width_of_bit-field;

};
where,
 data_type: It is an integer type that determines the bit-field value which is to be interpreted.
The type may be int, signed int, or unsigned int.
 member_name: The member name is the name of the bit field.
 width_of_bit-field: The number of bits in the bit-field. The width must be less than or equal
to the bit width of the specified type.

Applications of C Bit Fields


 If storage is limited, we can go for bit-field.
 When devices transmit status or information encoded into multiple bits for this type of
situation bit-field is most efficient.
 Encryption routines need to access the bits within a byte in that situation bit-field is quite
useful.

Example of C Bit Fields


In this example, we compare the size difference between the structure that does not specify bit
fields and the structure that has specified bit fields.

Structure Without Bit Fields

Consider the following declaration of date without the use of bit fields002

// C Program to illustrate the structure


without bit field
#include <stdio.h>

// A simple representation of the date


struct date {
unsigned int d;
unsigned int m;
unsigned int y;
};

int main()
{
// printing size of structure
printf("Size of date is %lu bytes\n",
sizeof(struct date));
struct date dt = { 31, 12, 2014 };
printf("Date is %d/%d/%d", dt.d, dt.m,
dt.y);
}

Learn Data Structures & Algorithms with GeeksforGeeks

Output
Size of date is 12 bytes
Date is 31/12/2014
The above representation of ‘date’ takes 12 bytes on a compiler whereas an unsigned int takes 4
bytes. Since we know that the value of d is always from 1 to 31, and the value of m is from 1 to
12, we can optimize the space using bit fields.

Structure with Bit Field


The below code defines a structure named date with a single member month. The month member is
declared as a bit field with 4 bits.

struct date
{
// month has value between 0 and 15,
// so 4 bits are sufficient for month variable.
int month : 4;
};
However, if the same code is written using signed int and the value of the fields goes beyond the bits
allocated to the variable, something interesting can happen.

Below is the same code but with signed integers:

// C program to demonstrate use of Bit-


fields
#include <stdio.h>

// Space optimized representation of the


date
struct date {
// d has value between 0 and 31, so
5 bits
// are sufficient
int d : 5;

// m has value between 0 and 15, so


4 bits
// are sufficient
int m : 4;

int y;
};

int main()
{
printf("Size of date is %lu
bytes\n",
sizeof(struct date));
struct date dt = { 31, 12, 2014 };
printf("Date is %d/%d/%d", dt.d,
dt.m, dt.y);
return 0;
}

Learn Data Structures & Algorithms with GeeksforGeeks

Output
Size of date is 8 bytes
Date is -1/-4/2014
Explanation

The output comes out to be negative. What happened behind is that the value 31 was stored in 5
bit signed integer which is equal to 11111. The MSB is a 1, so it’s a negative number and you need
to calculate the 2’s complement of the binary number to get its actual value which is what is done
internally.

By calculating 2’s complement you will arrive at the value 00001 which is equivalent to the decimal
number 1 and since it was a negative number you get a -1. A similar thing happens to 12 in which
case you get a 4-bit representation as 1100 and on calculating 2’s complement you get the value of
-4.

Interesting Facts About C Bit Fields

1. A special unnamed bit field of size 0 is used to force alignment on the next boundary.

Example: The below code demonstrates how to force alignment to the next memory boundary using
bit fields.

// C Program to illustrate the use of forced


alignment in
// structure using bit fields
#include <stdio.h>

// A structure without forced alignment


struct test1 {
unsigned int x : 5;
unsigned int y : 8;
};

// A structure with forced alignment


struct test2 {
unsigned int x : 5;
unsigned int : 0;
unsigned int y : 8;
};

int main()
{
printf("Size of test1 is %lu bytes\n",
sizeof(struct test1));
printf("Size of test2 is %lu bytes\n",
sizeof(struct test2));
return 0;
}

Learn Data Structures & Algorithms with GeeksforGeeks

Output
Size of test1 is 4 bytes
Size of test2 is 8 bytes

2. We cannot have pointers to bit field members as they may not start at a byte boundary.

Example: The below code demonstrates that taking the address of a bit field member directly is not
allowed.
// C program to demonstrate that the pointers
cannot point
// to bit field members
#include <stdio.h>
struct test {
unsigned int x : 5;
unsigned int y : 5;
unsigned int z;
};
int main()
{
struct test t;

// Uncommenting the following line will


make
// the program compile and run
printf("Address of t.x is %p", &t.x);

// The below line works fine as z is not a


// bit field member
printf("Address of t.z is %p", &t.z);
return 0;
}

Learn Data Structures & Algorithms with GeeksforGeeks

Output

prog.c: In function 'main':


prog.c:14:1: error: cannot take address of bit-field 'x'
printf("Address of t.x is %p", &t.x);
^

3. It is implementation-defined to assign an out-of-range value to a bit field member.

Example: The below code demonstrates the usage of bit fields within a structure and assigns an out-
of-range value to one of the bit field members.

// C Program to show what happends when out of


range value
// is assigned to bit field member
#include <stdio.h>

struct test {
// Bit-field member x with 2 bits
unsigned int x : 2;
// Bit-field member y with 2 bits
unsigned int y : 2;
// Bit-field member z with 2 bits
unsigned int z : 2;
};

int main()
{
// Declare a variable t of type struct test
struct test t;
// Assign the value 5 to x (2 bits)
t.x = 5;

// Print the value of x


printf("%d", t.x);

return 0;
}

Learn Data Structures & Algorithms with GeeksforGeeks

Output

Implementation-Dependent

4. Array of bit fields is not allowed.

Example: The below C program defines an array of bit fields and fails in the compilation.

// C Program to illustrate that we cannot have


array bit
// field members
#include <stdio.h>

// structure with array bit field


struct test {
unsigned int x[10] : 5;
};

int main() {}

Learn Data Structures & Algorithms with GeeksforGeeks

Output

prog.c:3:1: error: bit-field 'x' has invalid type


unsigned int x[10]: 5;
^

Most Asked Bit Field Interview Questions

Q1. Predict the output of the following program. Assume that unsigned int takes 4 bytes
and long int takes 8 bytes.

Ans:

#include <stdio.h>

struct test {
// Unsigned integer member x
unsigned int x;
// Bit-field member y with
33 bits
unsigned int y : 33;
// Unsigned integer member z
unsigned int z;
};

int main()
{
// Print the size of struct
test
printf("%lu", sizeof(struct
test));

return 0;
}

Learn Data Structures & Algorithms with GeeksforGeeks

Error:

./3ec6d9b7-7ae2-411a-a60e-66992a7fc29b.c:4:5: error: width of 'y'


exceeds its type
unsigned int y : 33;
^

Q2. Predict the output of the following program.

Ans:

#include <stdio.h>

struct test {
// Unsigned integer member x
unsigned int x;
// Bit-field member y with 33 bits
long int y : 33;
// Unsigned integer member z
unsigned int z;
};

int main()
{
// Declare a variable t of type struct
test
struct test t;
// Pointer to unsigned int, pointing to
member x
unsigned int* ptr1 = &t.x;
// Pointer to unsigned int, pointing to
member z
unsigned int* ptr2 = &t.z;

// Print the difference between the two


pointers
printf("%d", ptr2 - ptr1);

return 0;
}

Learn Data Structures & Algorithms with GeeksforGeeks

Output
4

Q3. Predict the output of the following program.

Ans:

#include <stdio.h>

union test {
// Bit-field member x with 3 bits
unsigned int x : 3;
// Bit-field member y with 3 bits
unsigned int y : 3;
// Regular integer member z
int z;
};

int main()
{
// Declare a variable t of type union test
union test t;
// Assign the value 5 to x (3 bits)
t.x = 5;
// Assign the value 4 to y (3 bits)
t.y = 4;
// Assign the value 1 to z (32 bits)
t.z = 1;
// Print the values of x, y, and z
printf("t.x = %d, t.y = %d, t.z = %d", t.x,
t.y, t.z);

return 0;
}

Learn Data Structures & Algorithms with GeeksforGeeks

Output
t.x = 1, t.y = 1, t.z = 1

Difference Between Structure and Union in C


Structures in C is a user-defined data type available in C that allows to combining of data items of
different kinds. Structures are used to represent a record.

Defining a structure: To define a structure, you must use the struct statement. The struct statement
defines a new data type, with more than or equal to one member. The format of the struct
statement is as follows:

struct [structure name]


{
member definition;
member definition;
...
member definition;
};

(OR)

struct [structure name]


{
member definition;
member definition;
...
member definition;
}structure variable declaration;
Union in C is a special data type available in C that allows storing different data types in the same
memory location. You can define a union with many members, but only one member can contain a
value at any given time. Unions provide an efficient way of using the same memory location for
multiple purposes.

Defining a Union: To define a union, you must use the union statement in the same way as you did
while defining a structure. The union statement defines a new data type with more than one
member for your program. The format of the union statement is as follows:

union [union name]


{
member definition;
member definition;
...
member definition;
};

(OR)

union [union name]


{
member definition;
member definition;
...
member definition;
}union variable declaration;

Similarities Between Structure and Union


1. Both are user-defined data types used to store data of different types as a single unit.
2. Their members can be objects of any type, including other structures and unions or arrays. A
member can also consist of a bit field.
3. Both structures and unions support only assignment = and sizeof operators. The two
structures or unions in the assignment must have the same members and member types.
4. A structure or a union can be passed by value to functions and returned by value by
functions. The argument must have the same type as the function parameter. A structure or
union is passed by value just like a scalar variable as a corresponding parameter.
5. ‘.’ operator or selection operator, which has one of the highest precedences, is used for
accessing member variables inside both the user-defined datatypes.

Differences between Structure and Union


Differences between Structure and Union are as shown below in tabular format as shown below as
follows:

Example
// C program to illustrate differences
// between structure and Union

#include <stdio.h>
#include <string.h>

// declaring structure
struct struct_example {
int integer;
float decimal;
char name[20];
};

// declaring union

union union_example {
int integer;
float decimal;
char name[20];
};
void main()
{
// creating variable for structure
// and initializing values difference
// six
struct struct_example s = { 18, 38,
"geeksforgeeks" };

// creating variable for union


// and initializing values
union union_example u = { 18, 38,
"geeksforgeeks" };

printf("structure data:\n integer: %d\n"


"decimal: %.2f\n name: %s\n",
s.integer, s.decimal, s.name);
printf("\nunion data:\n integer: %d\n"
"decimal: %.2f\n name: %s\n",
u.integer, u.decimal, u.name);

// difference two and three


printf("\nsizeof structure : %d\n",
sizeof(s));
printf("sizeof union : %d\n", sizeof(u));

// difference five
printf("\n Accessing all members at a
time:");
s.integer = 183;
s.decimal = 90;
strcpy(s.name, "geeksforgeeks");

printf("structure data:\n integer: %d\n "


"decimal: %.2f\n name: %s\n",
s.integer, s.decimal, s.name);

u.integer = 183;
u.decimal = 90;
strcpy(u.name, "geeksforgeeks");

printf("\nunion data:\n integer: %d\n "


"decimal: %.2f\n name: %s\n",
u.integer, u.decimal, u.name);

printf("\n Accessing one member at time:");

printf("\nstructure data:");
s.integer = 240;
printf("\ninteger: %d", s.integer);

s.decimal = 120;
printf("\ndecimal: %f", s.decimal);

strcpy(s.name, "C programming");


printf("\nname: %s\n", s.name);

printf("\n union data:");


u.integer = 240;
printf("\ninteger: %d", u.integer);

u.decimal = 120;
printf("\ndecimal: %f", u.decimal);

strcpy(u.name, "C programming");


printf("\nname: %s\n", u.name);

// difference four
printf("\nAltering a member value:\n");
s.integer = 1218;
printf("structure data:\n integer: %d\n "
" decimal: %.2f\n name: %s\n",
s.integer, s.decimal, s.name);

u.integer = 1218;
printf("union data:\n integer: %d\n"
" decimal: %.2f\n name: %s\n",
u.integer, u.decimal, u.name);
}

Output
structure data:
integer: 18
decimal: 38.00
name: geeksforgeeks

union data:
integer: 18
decimal: 0.00
name:

sizeof structure : 28
sizeof union : 20

Accessing all members at a time:structure data:


integer: 183
decimal: 90.00
name: geeksforgeeks

union data:
integer: 1801807207
decimal: 277322871721159507258114048.00
name: geeksforgeeks

Accessing one member at time:


structure data:
integer: 240
decimal: 120.000000
name: C programming

union data:
integer: 240
decimal: 120.000000
name: C programming

Altering a member value:


structure data:
integer: 1218
decimal: 120.00
name: C programming
union data:
integer: 1218
decimal: 0.00
name: ?
Time Complexity: O(1)

Auxiliary Space: O(1)

Note: Structures are better than unions since memory is shared in a union which
results in a bit of ambiguity. But technically speaking, unions are better in that they
help save a lot of memory, resulting in the overall advantage over structures in the
long run.
Quiz on structures and Union.

Anonymous Union and Structure in C


In C11 standard of C, anonymous Unions and structures were added.
Anonymous unions/structures are also known as unnamed unions/structures as they don’t have
names. Since there is no names, direct objects(or variables) of them are not created and we use
them in nested structure or unions.
Definition is just like that of a normal union just without a name or tag. For example,

// Anonymous union example


union
{
char alpha;
int num;
};
// Anonymous structure example
struct
{
char alpha;
int num;
};
Since there is no variable and no name, we can directly access members. This accessibility works
only inside the scope where the anonymous union is defined.
Following is a complete working example of anonymous union.

// C Program to demonstrate working of


anonymous union
#include <stdio.h>
struct Scope {
// Anonymous union
union {
char alpha;
int num;
};
};

int main()
{
struct Scope x, y;
x.num = 65;
y.alpha = 'A';

// Note that members of union are


accessed directly
printf("y.alpha = %c, x.num = %d",
y.alpha, x.num);

return 0;
}

Remember that we can only access one member of a union at a time. If another member is assigned
the previous member will be wiped out from the union.

Output
x.alpha = A, x.num = 65

// C Program to demonstrate working of anonymous


struct
#include<stdio.h>
struct Scope
{
// Anonymous structure
struct
{
char alpha;
int num;
};
};

int main()
{
struct Scope x;
x.num = 65;
x.alpha = 'B';

// Note that members of structure are


accessed directly
printf("x.alpha = %c, x.num = %d", x.alpha,
x.num);

return 0;
}

Output
x.alpha = B, x.num = 65
What about C++?
Anonymous Unions and Structures are NOT part of C++ 11 standard, but most of the C++
compilers support them. Since this is a C only feature, the C++ implementations don’t allow to
anonymous struct/union to have private or protected members, static members, and functions.

Enumeration (or enum) in C


Enumeration (or enum) is a user defined data type in C. It is mainly used to assign names to
integral constants, the names make a program easy to read and maintain.

Hereby mistake, the state of wed is 2, it should be 3. Please refer to the same example below for a better understanding.

enum State {Working = 1, Failed = 0};


The keyword ‘enum’ is used to declare new enumeration types in C and C++. Following is an
example of enum declaration.

// The name of enumeration is "flag" and the constant


// are the values of the flag. By default, the values
// of the constants are as follows:
// constant1 = 0, constant2 = 1, constant3 = 2 and
// so on.
enum flag{constant1, constant2, constant3, ....... };
Variables of type enum can also be defined. They can be defined in two ways:

// In both of the below cases, "day" is


// defined as the variable of type week.

enum week{Mon, Tue, Wed};


enum week day;

// Or

enum week{Mon, Tue, Wed}day;

// An example program to demonstrate


working
// of enum in C
#include<stdio.h>

enum week{Mon, Tue, Wed, Thur, Fri,


Sat, Sun};

int main()
{
enum week day;
day = Wed;
printf("%d",day);
return 0;
}

Output:

2
In the above example, we declared “day” as the variable and the value of “Wed” is allocated to day,
which is 2. So as a result, 2 is printed.
Another example of enumeration is:

// Another example program to


demonstrate working
// of enum in C
#include<stdio.h>

enum year{Jan, Feb, Mar, Apr, May, Jun,


Jul,
Aug, Sep, Oct, Nov, Dec};

int main()
{
int i;
for (i=Jan; i<=Dec; i++)
printf("%d ", i);

return 0;
}

Output:

0 1 2 3 4 5 6 7 8 9 10 11
In this example, the for loop will run from i = 0 to i = 11, as initially the value of i is Jan which is 0
and the value of Dec is 11.
Interesting facts about initialization of enum.
1. Two enum names can have same value. For example, in the following C program both ‘Failed’ and
‘Freezed’ have same value 0.

#include <stdio.h>
enum State {Working = 1, Failed = 0,
Freezed = 0};

int main()
{
printf("%d, %d, %d", Working, Failed,
Freezed);
return 0;
}

Output:

1, 0, 0
2. If we do not explicitly assign values to enum names, the compiler by default assigns values
starting from 0. For example, in the following C program, sunday gets value 0, monday gets 1, and
so on.

#include <stdio.h>
enum day {sunday, monday, tuesday, wednesday, thursday,
friday, saturday};

int main()
{
enum day d = thursday;
printf("The day number stored in d is %d", d);
return 0;
}

Output:

The day number stored in d is 4


3. We can assign values to some name in any order. All unassigned names get value as value of
previous name plus one.

#include <stdio.h>
enum day {sunday = 1, monday, tuesday = 5,
wednesday, thursday = 10, friday,
saturday};

int main()
{
printf("%d %d %d %d %d %d %d", sunday,
monday, tuesday,
wednesday, thursday, friday,
saturday);
return 0;
}

Output:

1 2 5 6 10 11 12
4. The value assigned to enum names must be some integral constant, i.e., the value must be in
range from minimum possible integer value to maximum possible integer value.
5. All enum constants must be unique in their scope. For example, the following program fails in
compilation.

enum state {working,


failed};
enum result {failed,
passed};

int main() { return 0; }

Output:

Compile Error: 'failed' has a previous declaration as 'state failed'


Exercise:
Predict the output of following C programs
Program 1:

#include <stdio.h>
enum day {sunday = 1, tuesday, wednesday, thursday,
friday, saturday};

int main()
{
enum day d = thursday;
printf("The day number stored in d is %d", d);
return 0;
}

Program 2:

#include <stdio.h>
enum State {WORKING = 0, FAILED, FREEZED};
enum State currState = 2;
enum State FindState() {
return currState;
}

int main() {
(FindState() == WORKING)? printf("WORKING"):
printf("NOT WORKING");
return 0;
}

Enum vs Macro
We can also use macros to define names constants. For example we can define ‘Working’ and ‘Failed’
using following macro.

#define
Working 0
#define Failed
1
#define
Freezed 2

There are multiple advantages of using enum over macro when many related named constants have
integral values.
a) Enums follow scope rules.
b) Enum variables are automatically assigned values. Following is simpler
CPP

enum state {Working, Failed,


Freezed};

C User-Defined Data Types

 C Structures
 dot (.) Operator in C
 C typedef
 Structure Member Alignment, Padding and Data Packing
 Flexible Array Members in a Structure in C
 C Unions
 Bit Fields in C
 Difference Between Structure and Union in C
 Anonymous Union and Structure in C
 Enumeration (or enum) in C

You might also like