Structures (struct) in C programming (detailed)

Banner

Structures are basic building blocks of object-oriented programming, if anyone practices C structures, they can understand and take a good leap in object-oriented programming. C structures are so definitive that they even let us know the pointer concept in a better way.

  • As we know, an array cannot be defined with different datatypes inside it, so structures are created to resolve the limitation of grouping variables with different data types together
  • Structures are the constructed datatypes in C, their general syntax is as follows
struct tag_name {
    datatype member1;
    datatype member2;
    ...
    datatype memberN;
};

  • The keyword struct defines the structure format
  • The tag_name can be used to declare structure variables of its type, later in the program
  • Variables defined inside the structure are structure elements or members
  • The structure format is called a template, note that it has not declared any variables
  • Even if the entire definition is considered as a statement, each member is declared independently for its name and type in a separate statement inside the template
  • The following example will help us to understand this better
book: author(char), title(char), price(float), year(int)

struct book {
    char author[20];
    char title[15];
    float price;
    int year;
};

  • One cannot assign values to the structure members at the time of initialization or definition
struct book {
    char author[20] = "some author Name";
    char title[15] = "Book Title";
    float price = 14.95;
    int year = 2017;
};

output:

Error
  • Variables can be declared along with struct keyword and tag-name
int main() {
    struct book book1, book2;
}

or

struct book {
    char author[20];
    char title[15];
    float price;
    int year;
} book1, book2;
  • Members are assigned values or accessed as follows
int main() {
    // declaration of structure variable
    struct book book1;

    // assign values to structure members
    strcpy(book1.author, "some author name");
    strcpy(book1.title, "Some Title");
    book1.price = 14.95;
    book1.year = 2017;

    // access structure members
    printf("Author: %s\nTitle: %s\nPrice: %f\nYear: %d\n", 
            book1.author, book1.title, book1.price, book1.year);

    return 0;
}

output:

Author: some author name
Title: Some Title
Price: 14.950000
Year: 2017
  • Members can also be assigned values while declaring a variable, however, the order must be according to the structure template
struct book book1 = {"some author name", "Some Title", 14.95, 2017};

or

struct book {
    char author[20];
    char title[15];
    float price;
    int year;
} book1 = {"some author name", "Some Title", 14.95, 2017};
  • Partial initialization is permitted, however, it is important to follow the order
// declaration of structure variable
struct book book1 = {"some author name", "some title"};

// assign values to structure members
book1.price = 14.95;
book1.year = 2017;

// not allowed
struct book book1 = {14.95, 2017};
  • The uninitialized members will be assigned default values, 0 (zero) for integers and floating point numbers, whereas, '\0' (null character) for characters and strings
  • Copying of one structure variable to another can be done the same way as ordinary variables (both variables must belong to the same structure)
struct book book1 = {"some author name", "some title"};

struct book book2;

// copying the data of one variable to another
book2 = book1;
  • Note that comparison statements such as book1 == book2 or book1 != book2 are not permitted, however, we need to perform comparisons between members individually, e.g. book1.price == book2.price
  • In the case of accessing members using pointers are as follows
struct book {
    char author[20];
    char title[15];
    float price;
    int year;
};

int main() {
    // declaring the structure variables including a pointer
    struct book b, *ptr;

    b = {"some author name", "Some Title", 14.95, 2017};

    // assigning the pointer variable
    ptr = &b;

    // accessing structure members using pointer variable
    printf("Author: %s\n", ptr->author);

    // or
    printf("Author: %s\n", (*ptr).author)

    retrurn 0;
}
  • Variables of structure can be considered as normal variables, one can create an array of them, or apply typedef
  • Structures can be used as a function parameter as well as a function return type
// update the price and year of a book using
// book structure by passing its variable as a parameter
// and return the same
struct book update(struct book argBook, float argPrice, int argYear) {
    argBook.price = argPrice;
    argBook.year = argYear;
    return argBook;
}

int main() {
    struct book book1 = {"some author name", "Some Title", 14.95, 2017};

    // display structure members
    printf("Initial Book1:\n");
    printf("Author: %s\nTitle: %s\nPrice: %f\nYear: %d\n", 
            book1.author, book1.title, book1.price, book1.year);

    // update price and year of existing book
    book1 = update(book1, 18.50, 2019);

    // display updated structure members
    printf("\nUpdated Book1:\n");
    printf("Author: %s\nTitle: %s\nPrice: %f\nYear: %d\n", 
            book1.author, book1.title, book1.price, book1.year);

    return 0;
}

output:

Initial Book1:
Author: some author name
Title: Some Title
Price: 14.950000
Year: 2017

Updated Book1:
Author: some author name
Title: Some Title
Price: 18.500000
Year: 2019
  • Pointer based function parameter is more dynamic in terms of memory and time
void update(struct book *argBook, float argPrice, int argYear) {
    argBook->price = argPrice;
    argBook->year = argYear;
}

int main() {
    struct book book1 = {"some author name", "Some Title", 14.95, 2017};

    // display structure members
    printf("Initial Book1:\n");
    printf("Author: %s\nTitle: %s\nPrice: %f\nYear: %d\n", 
            book1.author, book1.title, book1.price, book1.year);

    // update price and year of existing book
    update(&book1, 18.50, 2019);

    // display updated structure members
    printf("\nUpdated Book1:\n");
    printf("Author: %s\nTitle: %s\nPrice: %f\nYear: %d\n", 
            book1.author, book1.title, book1.price, book1.year);

    return 0;
}
  • Nested Structures or structures within a structure is permitted, whereas the internal structure must be initialized with a variable
struct address {
    char city[20];
    struct details {
        char name[20];
        int number;
        int floor;
        char wing;
    } apartment;
};

or

struct details {
    char name[20];
    int number;
    int floor;
    char wing;
};

struct address {
    char city[20];
    struct details apartment;
};
  • Three ways to access structure members
typedef struct {
    char author[20];
    char title[15];
    float price;
    int year;
} BOOK;

BOOK b, *ptr;
ptr = & b;

// using dot notation
b.year;
// using indirection notation
(*ptr).year;
// using selection notation
ptr -> year;
  • The size of structures can be returned by
// without typedef
struct book {
    char author[20];
    char title[15];
    float price;
    int year;
};

sizeof(struct book);

// with typedef
typedef struct {
    char author[20];
    char title[15];
    float price;
    int year;
} BOOK;

sizeof(BOOK);
  • Bit fields are such an interesting concept to use in structures, it is specifically used for programming in embedded systems
  • A set of adjacent bits whose size can be from 1 to 16 bits in length. A word can therefore be divided into a number of bit fields.
struct tag-name {
    data-type name1: bit-length;
    data-type name2: bit-length;
    ...
    data-type nameN: bit-length;
}
  • Bit fields always start with the first bit of the word (LSB)

That's all about structures in C, let me know if any one of you needs any help.