Introduction to C Programming

Introduction to C Programming by Rob Miles, Electronic Engineering


Structures

What is a Structure?
How Structures Work
Pointers to structures
Defining your own Types

What is a Structure?

Often when you are dealing with information you will want to hold a collection of different things about a particular item. For example, consider if the Nat. West. Bank commissioned you to write a customer database system. (it is in fact rather unlikely that this will happen - such systems are written in COBOL, not C!). Like any good programmer who has been on my course you would start by doing the following:

From your specification you know that the program must hold the following:

The Nat. West. have told you that they will only be putting up to 50 people into your database so, after a while you come up with the following:

#define MAX_CUST 50
#define NAME_LENGTH 30
#define ADDR_LENGTH 60
char name [NAME_LENGTH] [MAX_CUST] ;
char address [ADDR_LENGTH] [MAX_CUST] ; 
int account [MAX_CUST] ;
int balance [MAX_CUST] ;
int overdraft [MAX_CUST] ;

What we have is an array for each single piece of data we want to store about a particular customer. If we were talking about a database (which is actually what we are writing), the lump of data for each customer would be called a record and an individual part of that lump, for example the overdraft value, would be called a field. In our program we are working on the basis that balance[1] holds the balance of the first customer in our database, overdraft [1] holds the overdraft of the first customer, and so on.

This is all very well, and you could get a database system working with this data structure. However it would me much nicer to be able to lump your record together in a more definite way.

C lets you create data structures. A structure is a collection of C data types which you want to treat as a single entity. In C a lump of data would be called a structure and each part of it would be called a member. To help us with our bank database we could create a structure which could hold all the information about a customer :

struct customer
{
	char name [NAME_LENGTH] ;
	char address [ADDR_LENGTH] ;
	 int account ;
	int balance ;
	int overdraft ;
} ;

This defines a structure, called customer, which contains all the required customer information. Having done this we can now define some variables :

struct customer OnlyOne ;
struct customer EveryOne [MAX_CUST] ;

The first declaration sets up a variable called OnlyOne, which can hold the information for a single customer. The second declaration sets up an entire array of customers, called EveryOne which can hold all the customers.

We refer to individual members of a structure by putting their name after the structured variable we are using with a . separating them, for example :

OnlyOne.account

- would refer to the integer member account in the structured variable OnlyOne. You can do this with elements of an array of structures too, so that :

EveryOne [25].name

- would be the pointer to the part of memory containing the name of customer 25.


How Structures Work

Knowing how structures work makes using them a lot easier. We know that C is actually very simple minded about the way that it does things, this includes how it handles structures.

When C is given a struct definition it goes Aha! Here comes a structure. I will work out how much memory it needs and remember whereabouts in this chunk of memory each member starts. This means that for our bank example :

char name [30] The first 30 locations of the structure hold the name.

char address [60] The next 60 locations hold the address.

int account Next comes space for the account number

.. and so on. When you declare a variable of this structured type C makes a variable of the correct size. When you then do something like

OnlyOne.account = 99 ;

C says, I remember that the account value is stored after the 90 characters of the name and address members, and puts the value in the correct place.

If you have an array of structured variables, C just makes a variable with is :

size of array * size of structure

- in size and then fills in the members of each structure as it goes.

This means that, if you know how much memory int, float and char variables take up, you can work out how much memory any given structure needs. However, since C has already done this for you, it seems a little silly to have to do it manually. C provides a facility called sizeof (item). This returns the number of locations which the item takes up in memory. We could do things like :

printf ( "%d locations.\n", sizeof (struct customer) ) ;

It is very useful to be able to do this, particularly when you start sending the contents of structures to files.


Pointers to structures

You can have pointers to structured data types, just like you can point to any other type, for example

struct customer * cust_pointer ;

This is a pointer to a customer record. You would set it to point somewhere in the usual way :

cust_pointer = &OnlyOne ;

If you think about it, we must be able to use pointers to structures because we can have arrays of structures and we know that an array is simply a lump of memory of the appropriate size, with a pointer to the bottom of it.

C keeps track of pointer types for us. This is particularly important when we start modifying the value of a pointer, for example :

cust_pointer++ ;

This means increase the value of cust_pointer by one, i.e. make cust_pointer point to the next customer record in memory. C knows how many memory locations that a customer record takes, so it moves down memory that amount.

When we have used a pointer before we have used a * to de-reference it. Dereference means get me the thing that this pointer points at so that :

*cust_pointer
the -> is made up of the character minus (-) directly followed by the character greater than (>)
- means the structure pointed at by cust_pointer. When you want to get hold of one of the members of a structure which you are pointing at you have to tell C to de-reference the pointer to the structure and then return the required member. You do this by replacing the . between a structured variable and a member name with a -> between the pointer and the member name :
cust_pointer->balance = 0 ;

- would set the balance of the customer pointed at by cust_pointer to 0.


Defining your own Types

We have created our own types above, we can use them in our programs to hold specific kinds of data. However, we have to go through all the rigmarole of putting struct customer each time we want to declare a variable of that type. Also, at other points in the program we may want to use particular data types which mean something to us, how about a data type called inches which allows us to store values of inches. The reasons for doing this are not to make programs faster or smaller, but to make them easier to understand.

You can create a type using the new C keyword, typedef. This is followed by the type you want to declare :

typedef int inches ;

- this creates a new type called inches which is exactly the same as int. This means that we can put things in our program like :

inches width, height ;

- which declares width and height as variables of this type. This is a trivial, though useful, example. What we really want to do is create a new type which can hold our bank information:

typedef struct
{
	char name [NAME_LENGTH] ; 
	char address [ADDR_LENGTH] ; 
	int account ;
	int balance ; 
	int overdraft ;
} customer ;

Note that we have moved the name of the type we are creating to the end, and put the typdef keyword at the start.

Now we have a new type, called customer which we can use just like any other type :

customer Hull_Branch [100] ;
customer *New_Customer_Pointer ;

The structures above are used in just the same way as the ones we declared earlier, but their declaration is much simpler.


Rob Miles, R.S.Miles@e-eng.hull.ac.uk, Electronic Engineering
HTML by Bronwen Reid, July 1995