A structure is a customised user-defined data type in C. It is by definition a collection of variables of any type that are referenced under one name, providing a convenient means of keeping related information together.
Some terminology :-
structure definition :- the template used to create structure variables.
structure elements :- the member variables of the structure type
Defining Structures
struct tag { type var_1 ; type var_2 ; ... type var_n ; } ;
The keyword struct tells the compiler we are dealing with a structure and must be present whenever we refer to the new type, tag is an identifier which is the name given to the customised 'type'.
A variable of this new type can now be defined as follows for example. Note that the keyword struct has to be used in conjunction with our own name for the structure, tag.
struct tag variable ;
For Example :-
struct RECORD { int rec_no ; char name[30] ; char town[40] ; char country[ 20 ] } ; struct RECORD person ;
The compiler will automatically allocate enough storage to accommodate all the elements. To find out how much storage is required one might do the following
size = sizeof ( person ) ; or size = sizeof( struct RECORD ) ;
NOTE : The name of a structure is not the address of the structure as with array names.
For example define a complex type structure as follows.
struct complex { double real ; double imaginary ; // Note that a variable may also be } cplx ; // defined at structure definition time
The elements of the structure are accessed using the dot operator, . , as follows
cplx.real = 10.0 ; cplx.imag = 20.23 ; scanf ( "%lf", &cplx.real ) ;
or if we want to access struct RECORD already defined
puts( person.name ) ;
or character by character
person.name[i] = 'a' ;
Thus we treat structure elements exactly as normal variables and view the dot operator as just another appendage like the indirection operator or an array index.
Structure elements or fields can be initialised to specific values as follows :-
struct id { char name[30] ; int id_no ; } ; struct id student = { "John", 4563 } ;
The name of a structure variable can be used on its own to reference the complete structure. So instead of having to assign all structure element values separately, a single assignment statement may be used to assign the values of one structure to another structure of the same type.
For Example :
struct { int a, b ; } x = {1, 2 }, y ; y = x ; // assigns values of all fields in x to fields in y
Once again emphasising that structures are just like any other type in C we can create arrays of structures, nest structures, pass structures as arguments to functions, etc.
For example we can nest structures as follows creating a structure employee_log that has another structure as one of its members.
struct time { int hour ; int min ; int sec ; } ; struct employee_log { char name[30] ; struct time start, finish ; } employee_1 ;
To access the hour field of time in the variable employee_1 just apply the dot operator twice
employee_1.start.hour = 9 ;
Typically a company will need to keep track of more than one employee so that an array of employee_log would be useful.
struct employee_log workers[100] ;
To access specific employees we simply index using square braces as normal, e.g. workers[10]. To access specific members of this structure we simply apply the dot operator on top of the index.
workers[10].finish.hour = 10 ;
When structures or arrays of structures are not global they must be passed to functions as parameters subject to the usual rules. For example
function1( employee_1 ) ;
implements a call to function1 which might be prototyped as follows
void function1( struct employee_log emp ) ;
Note however that a full local copy of the structure passed is made so if a large structure is involved memory the overhead to simply copy the parameter will be high so we should employ call by reference instead as we will see in the next section.
Passing an array of structures to a function also follows the normal rules but note that in this case as it is impossible to pass an array by value no heavy initialisation penalty is paid - we essentially have call by reference. For example
function2( workers ) ;
passes an array of structures to function2 where the function is prototyped as follows.
function2( struct employee_log staff[ ] ) ;
As we have said already we need call by reference calls which are much more efficient than normal call by value calls when passing structures as parameters. This applies even if we do not intend the function to change the structure argument.
A structure pointer is declared in the same way as any pointer for example
struct address { char name[20] ; char street[20] ; } ; struct address person ; struct address *addr_ptr ;
declares a pointer addr_ptr to data type struct address.
To point to the variable person declared above we simply write
addr_ptr = &person ;
which assigns the address of person to addr_ptr.
To access the elements using a pointer we need a new operator called the arrow operator, ->, which can be used only with structure pointers. For example
puts( addr_ptr -> name ) ;
For Example :- Program using a structure to store time values.
#include <stdio.h> struct time_var { int hours, minutes, seconds ; } ; void display ( const struct time_var * ) ; /* note structure pointer and const */ void main() { struct time_var time ; time.hours = 12 ; time.minutes = 0 ; time.seconds = 0 ; display( &time ) ; } void display( const struct time_var *t ) { printf( "%2d:%2d;%2d\n", t -> hours, t -> minutes, t -> seconds ) ; }
Note that even though we are not changing any values in the structure variable we still employ call by reference for speed and efficiency. To clarify this situation the const keyword has been employed.
The memory allocation functions may also be used to allocate memory for user defined types such as structures. All malloc() basically needs to know is how much memory to reserve.
struct coordinate { int x, y, z ; } ; struct coordinate *ptr ; ptr = (struct coordinate * ) malloc( sizeof ( struct coordinate ) ) ;
All Rights Reserved. © 2024 BookOfNetwork