Complex data types
A data structure ("struct") contains multiple pieces of data. Each piece of data (called a "member")
can be accessed by the name of the variable, followed by a '.', then the name of the member.
(Another way to access a member is using the member operator '>'). The member variables of a struct can be of any data type and can even be an array or a pointer.
(Another way to access a member is using the member operator '>'). The member variables of a struct can be of any data type and can even be an array or a pointer.
Pointers
Pointers are variables that don't hold the actual data. Instead they point to the memory location of some other variable. For example,
int *pointer = &variable;
defines a pointer to an int, and also makes it point to the particular integer contained in variable.
The '*' is what makes this an integer pointer. To make the pointer point to a different integer, use the
form
form
pointer = &sandwitches;
Where & is the address of operator. Often programmers set the value of the pointer to NULL like
this:
this:
pointer = 0;
which tells us that the pointer isn't currently pointing to any real location.
Additionally, to dereference (access the thing being pointed at) the pointer, use the form:
value = *pointer;
Structs
A data structure contains multiple pieces of data. One defines a data structure using the struct keyword. For example,
struct mystruct
{
{
int int_member;
double double_member;
char string_member[25]; } variable;
variable is an instance of mystruct. You can omit it from the end of the struct declaration and declare it later using:
struct mystruct variable;
It is often common practice to make a type synonym so we don't have to type "struct mystruct" all
the time. C allows us the possibility to do so using a typedef statement, which aliases a type:
the time. C allows us the possibility to do so using a typedef statement, which aliases a type:
typedef struct
{
} Mystruct;
The struct itself has no name (by the absence of a name on the first line), but it is aliased as Mystruct. Then you can use
Mystruct variable;
Note that it is commonplace, and good style to capitalize the first letter of a type synonym.
However in the actual definition we need to give the struct a tag so we can refer to it: we may have a recursive data structure of some kind.
Unions
The definition of a union is similar to that of a struct. The difference between the two is that in a
struct, the members occupy different areas of memory, but in a union, the members occupy the same area of memory. Thus, in the following type, for example:
union {
int i;
double d;
} u;
The programmer can access either u.i or u.d, but not both at the same time. Since u.i and u.d occupy the same area of memory, modifying one modifies the value of the other, sometimes in
unpredictable ways.
unpredictable ways.
The size of a union is the size of its largest member.
Type modifiers
register is a hint to the compiler to attempt to optimise the storage of the given variable by
storing it in a register of the computer's CPU when the program is run. Most optimising compilers do this anyway, so use of this keyword is often unnecessary. In fact, ANSI C states that a compiler can ignore this keyword if it so desires and many do. Microsoft Visual C++ is an example of an implementation that completely ignores the register keyword.
volatile is a special type modifier which informs the compiler that the value of the variable may
be changed by external entities other than the program itself. This is necessary for certain programs
compiled with optimisations if a variable were not defined volatile then the compiler may
assume that certain operations involving the variable were safe to optimise away when in fact they
aren't. volatile is particularly relevant when working with embedded systems (where a program may not have complete control of a variable) and multithreaded applications.
be changed by external entities other than the program itself. This is necessary for certain programs
compiled with optimisations if a variable were not defined volatile then the compiler may
assume that certain operations involving the variable were safe to optimise away when in fact they
aren't. volatile is particularly relevant when working with embedded systems (where a program may not have complete control of a variable) and multithreaded applications.
auto is a modifier which specifies an "automatic" variable that is automatically created when in
scope and destroyed when out of scope. If you think this sounds like pretty much what you've been
doing all along when you declare a variable, you're right: all declared items within a block are
implicitly "automatic". For this reason, the auto keyword is more like the answer to a trivia question
than a useful modifier, and there are lots of very competent programmers that are unaware of its
existence.
extern is used when a file needs to access a variable in another file that it may not have #included
directly. Therefore, extern does not actually carve out space for a new variable, it just provides the
compiler with sufficient information to access the remote variable. scope and destroyed when out of scope. If you think this sounds like pretty much what you've been
doing all along when you declare a variable, you're right: all declared items within a block are
implicitly "automatic". For this reason, the auto keyword is more like the answer to a trivia question
than a useful modifier, and there are lots of very competent programmers that are unaware of its
existence.
0 comments:
Post a Comment