C Structures

C Structures

In C, a structure is a custom data type that enables you to group together items of potentially different data types into a single type. To define a structure in the C programming language, you use the “struct” keyword. The individual items contained within the structure are known as its members, and they can be of any valid data type. Structures are commonly used to create complex data structures that represent real-world entities or data with multiple attributes, allowing for more organized and versatile data management in C programs.

C Structure Declaration

Initially, we have to declare the c structure before using in C program,

In a structure declaration in C, you define the member variables and their data types. To declare a structure, you use the “struct” keyword, and the syntax typically follows this pattern:

Syntax

struct structure_name {
    data_type member_name1;
    data_type member_name1;
    ....
    ....
};

The syntax provided above is known as the structure template and also, no memory is allocated with it.

C Structure Definition

We have to define structure before applying in the program. Hence, we can define structure in 2 ways:

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 beforehand
struct structure_name variable1, variable2, .......;

Access Structure Members

With the help of (.)dot operators, we can access structure members.

Syntax

structure_name.member1;
strcuture_name.member2;

Initialize Structure Members

We can understand that from the program give below that the structure members cannot be initialized with the declaration. Thus, C program will fail in the compilation.

struct Point
{
   int x = 0;  // COMPILER ERROR:  cannot initialize members here
   int y = 0;  // COMPILER ERROR:  cannot initialize members here
};

In C, when you declare a data type, no memory is allocated for it until you create variables of that type. Once variables are created, memory is allocated for each instance. Th 3 methods to initialize structure members are the 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 };

Here, values are provided in sequential order.

3. Initialization using a Designated Initializer List

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

Structure members will be initialized in any order.

Example of Structure in C



// 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, "Skill vertex" }, 
                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 = Skillvertex
Struct 2:
    i = 1, c = A, f = 1.000000, s = Skillvertex
Struct 3
    i = 5, c = a, f = 5.000000

Typedef for Structures

For structures, using the typedef keyword allows you to create a shorter and more convenient name for the structure type. This can help improve code readability and manageability, as you can use the shorter alias throughout your code instead of the longer structure name with the struct keyword.

// 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 Structure

C structure will enable us to insert from one structure into another as a member. This process is referred as nesting and such structures are called nested structure . There are 2 methods to do nesting and they are given below:

1. Embedded Structure Nesting

Structure is hence 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 C programming known as “nesting structures” or “structure composition.” In this approach, you declare one structure within another structure to create a nested or hierarchical data structure.

Example:

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

struct parent {
    int member1;
    struct member_str member2;
    ...
}

The declaration provided below is invalid:

struct parent {
    struct mem a;
};

struct mem {
    int var;
};

Accessing Nested Members

Similarly, we can access nested with using .dot operator twice .

Example

str_parent.str_child.member;

Example:

// 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

In C, you can define pointers that point to structures, just like you would with any other variable. These are typically referred to as “Structure Pointers.” Structure pointers allow you to work with and manipulate structures indirectly by pointing to them. To access the members of a structure that’s pointed to by a structure pointer, you use the arrow (->) operator.

// 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

Self-referential structures, also known as recursive structures, are structures in C that contain references to the same type, essentially creating a circular or nested structure. This is achieved by including a member within the structure that is a pointer to the same structure type. Such structures are often used in scenarios where a hierarchical or nested data structure is needed.

Example

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

C Structure Padding and Packing

  1. Structure Padding: In C, the size of a structure should technically be the sum of the sizes of its members. However, due to memory alignment and optimization considerations, the actual size of a structure may be larger. Structure padding is the practice of adding empty bytes within the structure to align its data members naturally in memory. The goal is to minimize the CPU read cycles for data retrieval.
  2. Structure Packing: There are situations where you need to pack the structure more tightly, removing the empty bytes to conserve memory. This is particularly important in scenarios where memory efficiency is critical. C provides two common methods for achieving structure packing:
    • Using #pragma pack(1): This is a compiler-specific directive that sets the packing alignment to 1 byte. It instructs the compiler to minimize padding within the structure.
    • Using __attribute((packed))__: This is another compiler-specific attribute used to achieve structure packing. It’s common in GCC-based compilers and serves a similar purpose as #pragma pack(1).

Example

// 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

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

struct structure_name {
    data_type member_name: width_of_bit-field;
};

Example


// 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

Use of Structure in C

  1. Custom Data Types: Structures in C can be used to define custom data types that are not present in the language’s built-in types. This allows you to create complex data types, such as representing dates, times, complex numbers, or other domain-specific data structures.
  2. Data Organization: Structures are often used to organize and group related data into a single data structure. This can be helpful when dealing with a large amount of data that can be logically divided into different fields or attributes.
  3. Data Structures: Structures are essential for creating more complex data structures like trees, linked lists, stacks, and queues. These data structures are the building blocks for many algorithms and applications.
  4. Returning Multiple Values: Structures are a useful way to return multiple values from a function. Instead of returning individual values, you can package related data into a structure and return that structure from a function. This is especially beneficial when a function needs to return several pieces of data that are conceptually related.

In essence, structures provide a powerful tool in C for data organization, abstraction, and creating custom data types to represent a wide range of real-world entities and data structures.

Limitations of C Structures

Advantages of C Structures:

  1. Data Packing: Structures provide a way to group data items of different types into a single unit, which is useful for handling logically related data.

Limitations of C Structures:

  1. Higher Memory Consumption: Due to structure padding, C structures may consume more memory than expected. This can be inefficient, especially when memory is a concern.
  2. No Data Hiding: C structures do not support data hiding or encapsulation. All members of a structure are typically accessible from any function within the structure’s scope, which can lead to unintended changes to the structure’s data.
  3. Functions Inside Structure: C structures do not allow the inclusion of functions within the structure. In object-oriented languages, you can have methods associated with a structure (class), but in C, this is not a feature of structures.
  4. Static Members: C structures cannot have static members. Static members are not supported within the body of a structure.
  5. Construction Creation: C structures do not have constructors. Unlike object-oriented languages, you cannot define constructors for structures in C.

It’s important to be aware of these limitations when working with C structures and to consider whether they align with your specific programming requirements. If encapsulation and associated functions are needed, other programming paradigms, such as object-oriented programming in C++ or other languages, may be more appropriate.

FAQ-C Structures

Q1. What is a structure in programming?

Ans. Structures, or structs, group related variables into a single entity. Each variable in a struct is called a member. Unlike arrays, structs can hold different data types, like integers, floats, and characters. They’re used to organize and manage related data efficiently.

Q2. How to create a data structure in C?

Ans. #include <stdio. h>
#include <stdlib. h>
struct Node {
int data;
struct Node *next;
};
void printList(struct Node *node) {
while (node != NULL) {

Q3. What is a structure tag in C?

Ans. A structure can have an optional identifier called a “tag,” which provides the name for the structure type. This tag can be used when referencing the structure type in other parts of the program.


Hridhya Manoj

Hello, I’m Hridhya Manoj. I’m passionate about technology and its ever-evolving landscape. With a deep love for writing and a curious mind, I enjoy translating complex concepts into understandable, engaging content. Let’s explore the world of tech together

Leave a Comment