آموزش زبان c قسمت بیست و سوم:
is an int. You may be feeling a little disappointed at the way in which structures are used. When you first meet arrays it is obvious how useful they are because the array index is an integer which can be used within a loop to process vast amounts of data in a few lines of code. When you first meet the struct it just doesn't have the same obvious advantages. Because you have to write out a full qualified name to get at each of the components of the struct you can't automate the processing in the same way. However this is reasonable enough when you remember that each component of a struct can be a different data type! The point is that the value of a struct is different to that of an array. A struct can be used to wrap up a group of variables which form a coherent entity.
For example, C has no facilities for manipulating complex numbers but this is easy enough to put right using a struct and a few functions. A complex number is composed of two parts - a real and imaginary part - which can be implemented as single or double precision values. This suggests defining a new struct type:
struct comp
{
float real;
float imag;
};
After this you can declare new complex variables using something like:
struct comp a,b;
The new complex variables cannot be used as if they were simple variables - because they are not. Most versions, of the C language do allow you to assign structures so you could write:
a=b;
as shorthand for
a.real=b.real;
a.imag=b.imag;
Being able to assign structures is even more useful when they are bigger. However you can't expect C to sort out what you mean by c = a + b - for this you have to write out the rule for addition as:
c.real=a.real+b.real;
c.imag=a.imag+b.imag;
Of course a sensible alternative to writing out the addition each time is to define a function to do the same job - but this raises the question of passing structures as parameters. Fortunately this isn't a big problem. Most C compilers, will allow you to pass entire structures as parameters and return entire structures. As with all C parameters structures are passed by value and so if you want to allow a function to alter a parameter you have to remember to pass a pointer to a struct. Given that you can pass and return structs the function is fairly easy:
struct comp add(struct comp a , struct comp b)
{
struct comp c;
c.real=a.real+b.real;
c.imag=a.imag+ b.imag;
return c;
}
After you have defined the add function you can write a complex addition as:
x=add(y,z)
which isn't too far from the x=y+z that you would really like to use. Finally notice that passing a struct by value might use up rather a lot of memory as a complete copy of the structure is made for the function.
You can define a pointer to a structure in the same way as any pointer to any type. For example:
struct emprec *ptr
defines a pointer to an emprec. You can use a pointer to a struct in more or less the same way as any pointer but the use of qualified names makes it look slightly different For example:
(*ptr).age
is the age component of the emprec structure that ptr points at - i.e. an int. You need the brackets because '.' has a higher priority than '*'. The use of a pointer to a struct is so common, and the pointer notation so ugly, that there is an equivalent and more elegant way of writing the same thing. You can use:
prt->age
to mean the same thing as (*ptr).age. The notation gives a clearer idea of what is going on - prt points (i.e. ->) to the structure and .age picks out which component of the structure we want. Interestingly until C++ became popular the -> notation was relatively rare and given that many C text books hardly mentioned it this confused many experienced C programmers!
There are many reasons for using a pointer to a struct but one is to make two way communication possible within functions. For example, an alternative way of writing the complex number addition function is:
void comp add(struct comp *a , struct comp *b , struct comp *c)
{
c->real=a->real+b->real;
c->imag=a->imag+b->imag;
}
In this case c is now a pointer to a comp struct and the function would be used as:
add(&x,&y,&z);
Notice that in this case the address of each of the structures is passed rather than a complete copy of the structure - hence the saving in space. Also notice that the function can now change the values of x, y and z if it wants to. It's up to you to decide if this is a good thing or not!
Malloc
Now we come to a topic that is perhaps potentially the most confusing. So far we have allowed the C compiler to work out how to allocate storage. For example when you declare a variable:
int a;