C Essentials basics | Page 8

Not Available
fraction
(the whole
block of
memory)int
(within
block of
memory)ExpressionTypef1struct fraction*
*f1struct fraction
(*f1).numeratorint
There's an alternate, more readable syntax available for dereferencing a pointer to a
struct. A "->" at the right of the pointer can access any of the fields in the struct. So the
reference to the numerator field could be written f1->numerator.
Here are some more complex declarations...
struct fraction** fp;// a pointer to a pointer to a struct fraction
struct fraction fract_array[20]; // an array of 20 struct fractions
struct fraction* fract_ptr_array[20];// an array of 20 pointers to
// struct fractions
One nice thing about the C type syntax is that it avoids the circular definition problems
which come up when a pointer structure needs to refer to itself. The following definition
defines a node in a linked list. Note that no preparatory declaration of the node pointer
type is necessary.
struct node {
int data;
struct node* next;
};
The & Operator
The & operator is one of the ways that pointers are set to point to things. The & operator
computes a pointer to the argument to its right. The argument can be any variable which
takes up space in the stack or heap (known as an "LValue" technically). So &i and
&(f1->numerator) are ok, but &6 is not. Use & when you have some memory, and
you want a pointer to that memory.

19
void foo() {
int* p; // p is a pointer to an integer
int i; // i is an integer
p = &i; // Set p to point to i
*p = 13; // Change what p points to -- in this case i -- to 13
// At this point i is 13. So is *p. In fact *p is i.
}p13iWhen using a pointer to an object created with &, it is important to only use the pointer so
long as the object exists. A local variable exists only as long as the function where it is
declared is still executing (we'll see functions shortly). In the above example, i exists
only as long as foo() is executing. Therefore any pointers which were initialized with
&i are valid only as long as foo() is executing. This "lifetime" constraint of local
memory is standard in many languages, and is something you need to take into account
when using the & operator.
NULL
A pointer can be assigned the value 0 to explicitly represent that it does not currently
have a pointee. Having a standard representation for "no current pointee" turns out to be
very handy when using pointers. The constant NULL is defined to be 0 and is typically
used when setting a pointer to NULL. Since it is just 0, a NULL pointer will behave like
a boolean false when used in a boolean context. Dereferencing a NULL pointer is an error
which, if you are lucky, the computer will detect at runtime -- whether the computer
detects this depends on the operating system.
Pitfall -- Uninitialized Pointers
When using pointers, there are two entities to keep track of. The pointer and the memory
it is pointing to, sometimes called the "pointee". There are three things which must be
done for a pointer/pointee relationship to work...
(1) The pointer must be declared and allocated
(2) The pointee must be declared and allocated
(3) The pointer (1) must be initialized so that it points to the pointee (2)
The most common pointer related error of all time is the following: Declare and allocate
the pointer (step 1). Forget step 2 and/or 3. Start using the pointer as if it has been setup
to point to something. Code with this error frequently compiles fine, but the runtime
results are disastrous. Unfortunately the pointer does not point anywhere good unless (2)
and (3) are done, so the run time dereference operations on the pointer with * will misuse
and trample memory leading to a random crash at some point.

20
{
int* p;
*p = 13;// NO NO NO p does not point to an int yet
// this just overwrites a random area in memory
}-14346piOf course your code won't be so trivial, but the bug has the same basic form: declare a
pointer, but forget to set it up to point to a particular pointee.
Using Pointers
Declaring a pointer allocates space for the pointer itself, but it does not allocate space
for the pointee. The pointer must be set to point to something before you can dereference
it.
Here's some code which doesn't do anything useful, but which does demonstrate (1) (2)
(3) for pointer use correctly...
int* p;// (1) allocate the pointer
int i;// (2) allocate pointee
struct fraction f1;// (2) allocate pointee
p = &i;// (3) setup p to point to i
*p = 42;// ok to use p since it's setup
p = &(f1.numerator);// (3) setup p to point to a different int
*p = 22;
p = &(f1.denominator);// (3)
*p = 7;
So far we have just used the & operator to create pointers to simple variables such as i.
Later, we'll see other ways of getting pointers with arrays and other techniques.
C Strings
C has minimal support of character strings. For the most part, strings operate as ordinary
arrays of characters. Their maintenance is
Continue reading on your phone by scaning this QR Code

 / 18
Tip: The current page has been bookmarked automatically. If you wish to continue reading later, just open the Dertz Homepage, and click on the 'continue reading' link at the bottom of the page.