Structures

A structure is a user-defined collection of one or more variables grouped under a single name. This allows a programmer to wrap related variables with different data types into a single entity. This makes it easier to manipulate data in the program. The variables in a structure can be of different data types. Each variable within a structure is called a member of the structure.

Defining and Declaring Structures

The struct keyword is used to declare the beginning of a structure definition followed immediately by the name of the structure. Following the structure tag is an opening curly brace followed by a list of the structure’s member variables and a closing curly brace. Once the structure type has been defined, variables of that structure type can then be declared with structure definition or after the structure is defined (see below)

struct account
{
int accountno;
char *lastname;
char *firstname;
int age;
unsigned int telephone;
} user1;//structure variable defined with structure
struct account user2, user3;//structure variable outside of the structurevid, Jack;

Note: In C++, the struct keyword is optional before the variable declaration. In C, it is compulsory.

Accessing Members of a Structure

Structure members are accessed using the dot operator between the structure and the member name. Thus, to set the value of variable age for user1 in the above structure account use the following -

user1.age = 21;

Initialise Structures

When initialising a struct, the initialiser consists of a brace-enclosed, comma-separated list of values in the same order as the variables in the structure definition.

For instance to initialise a struct variable user4 using the structure above -

struct account user4={123,"john","doe",12,123456789};

Structure members cannot be initialised within the declaration because when a datatype is declared, no memory is allocated for that datatype. Memory is allocated only when variables are created.

Designated Initialisation - allows structure members to be initialised in any order. Each value is preceded by a designated initialiser corresponding to the structure variable name. Initialisation then moves forward in order of declaration if no further designated initialisers are specified. This feature has been added to the C99 standard. For example -

struct account user5={.lastname="jill","doe",123456789};

Any remaining members not initialised will be set to Zero.

Arrays of Structures

An array of structures is a sequential collection of structures. After the structure has been defined, an array of structures is declared as follows-

struct userdetails list[100];

The above statement declares an array named list that contains 100 elements. Each element is a structure of type userdetails and is identified by subscript. The structure data can be manipulated by specifying the appropriate index value of the array. Like a standard Array, an array of structures can be initialised at compile time.

Structures and Pointers

Structures can be accessed and manipulated by pointers. Pointers to structures can be declared by preceding the variable name with an asterisk. The individual member variables are accessed using the operator instead of the .(dot) operator

#include <stdio.h>
int main(void)
{
struct account{
unsigned int accountno;
char *firstname;
char *lastname;
unsigned int telephone;
} user1={123,"joe","blogs",123456789};//structure variable user1 defined and initiated
struct account *ptrStr;//create pointer of type struct account
ptrStr = &user1;//set pointer to address of user1
printf("%d %s %s %d", ptrStr->accountno,ptrStr->firstname, ptrStr->lastname,ptrStr->telephone);//access elements using ->
return 0;
}

Passing Structures as Arguments to Functions

An entire structure can be passed to a function as a parameter. This structure can be transferred to a function either using call by value or call by reference scheme

#include <stdio.h>
struct account{ //declare stucture
unsigned int accountno;
char *firstname;
char *lastname;
unsigned int telephone;
};
void function1(struct account user1copy) //declare fuction with argument type struct account
{
printf("%d\n",user1copy.accountno);
printf("%s\n",user1copy.firstname);
printf("%s\n",user1copy.lastname) ;
printf("%d\n",user1copy.telephone);
}

int main(void)
{
struct account user1={123,"joe","blogs",123456789};//initialise structure
function1(user1);//call structure passing parameter user1
return 0;
}


Passing a structure parameter by value
 – To pass a structure parameter by value declare the function to use the structure type. When the function is called, the function creates and uses a copy of the structure. Any modification to the structure made inside the function won't affect the original value.

Passing a structure parameter by reference - To change the structure inside of our function, then it must be passed by reference. Any changes made to the structure members are reflected in the original structure. This is because pointers deal directly with the data stored in the memory.

Structures Within Structures

In C, a structure declaration can be placed inside another structure (nesting). This declaration can either be an Embedded Structure Declaration or by making two separate structure declarations.

#include <stdio.h>
int main(void) {
struct outer {//declare outer stucture
int member1;
int member2;
int member3;

struct embedded{//declare inner structure
int member_1;
int member_2;
int member_3;
} embeddedvar;//declare inner struct variable
} outervar={3,4,5,{1,2,3}};//declare outer stuct variable and initialise outer values and then inner values

// structure embedded
printf("%d", outervar.embeddedvar.member_1);//output embedded member_1
printf("%d", outervar.member1);//output member1
return 0;
}  

Separate nested Structure example

#include <stdio.h>
int main(void) {
struct embedded
{
int member_1;
int member_2;
int member_3;
};

struct outer
{
struct embedded embeddedvar; //declare embadded variable
int member1;
int member2;
int member3;
} outervar={{1,2,3},3,4,5};

printf("%d", outervar.embeddedvar.member_1);
printf("%d", outervar.member1);
return 0;
}