Objects

C, like many languages, makes a sharp division between `objects' and `values'.  Values are ephemeral -- fleeting things that evaporate away if you do not save them.  To save them, you store them into objects.

The definition of an object, in the C99 standard, is:

A region of data storage in the execution environment, the contents of which can represent values.  Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined.  When referenced, an object may be interpreted as having a particular type; see 6.2.2.1.
In other words, objects are just collections of bytes.  (Beware, however: these are `C bytes', which may or may not be the same as `hardware bytes'.  For better or worse, C defines a `byte' as a char, and vice versa.  This could mean that a `C byte' might be 16 or 32 bits even though the hardware supports 8-bit objects directly.)

The raw bits stored in the bytes making up an object have a special name: they are the representation of the value stored in that object.  In some cases, there is exactly one representation per value, and vice versa, but this is not always true.  The relationship between representations and values tends to be as simple or complex as that provided by the hardware, and some hardware uses rather ornate representations.

Objects are often found via `identifiers' (link?), but C allows for the existence of anonymous objects, particularly those created through the malloc() function.

Object properties - duration

Objects generally have a particular type (such as int or double), set at the time the object is created, and fixed for the lifetime of that object.  As the definition above hints, there are ways to sneak around this.  On the other hand, objects always have a specific lifetime, also called a storage duration.

When an object is associated with an ordinary identifier, its duration is either static or automatic.  Whenever you declare an ordinary variable, this creates an object.  The storage duration of that object depends on where and how the variable is defined.  This duration also interacts with the initial value of that object, if any.

Any object with static duration `lives forever', and always has an initial value, even if you do not give it one.  Such objects are created by the time your program enters its main() function, and remain in memory until the program exits.  (The C standards say nothing about what happens after exit -- perhaps they remain in memory even then!)  If you do not give a static-duration object an initial value, the compiler must act as if you assigned an integer-constant zero to it.  That means that static-duration ints are initially 0, doubles are 0.0, and pointers are NULL.  Of course, if you want other programmers to be aware that you really intended them to be set to zero, you can always initialize them explicitly.  On many systems this requires slightly more space in the executable program (per initialized variable).

An object with automatic duration, on the other hand, lives only from the time it is created `automatically', at function or block entry, until the block in which that variable lives is exited (either by normal control flow, or a goto, or returning from a function, or any other way to exit a block).  If you do not initialize such a variable yourself, its initial value will be junk or garbage, and possibly even `poisonous'.  You must assign a value to such a variable before you use it in any other way.  (Some programmers like to assign every such variable a value, even if they have no particular value to put into it yet, just so that any bugs that result from using the variable before setting it to its proper value are at least consistent.  The garbage values often change from one run to the next, on some computers.  Some compilers, on the other hand, can detect the use of an uninitialized variable and produce a compile-time diagnostic, thus catching the bug even before the program is tested -- so some programmers prefer to leave them uninitialized.)

The third kind of duration is called allocated duration.  Such objects are created by the malloc() function, and live in memory until a corresponding free() call.  As with automatic-duration objects, these have garbage initial values.  Use of allocated duration requires pointers.

A misleading keyword

The meaning of the C keyword static should seem completely obvious now.  If there is a `static duration', and a static keyword, they should correspond.  And they do -- but not exactly.

Ordinary variables can be declared outside of any function or block, and also inside functions and blocks.  (The exact constraints on declarations differ between C89 and C99.)  Since automatic-duration objects only `live' while their function or block is executing, it stands to reason that only variables inside a function or block can have automatic duration.  That in turn implies that variables outside a function or block must have static duration, and indeed, this is the case.  Thus, only function- and block-scope variables need the keyword.  Using the static keyword in such a declaration changes the corresponding variable's duration to static -- so we can say that a static variable has static duration.  This leaves no need for the keyword for variables outside a function (or, indeed, for functions themselves).  But the keyword can still be applied to them; there, it has another meaning entirely.

What this really means is that whenever a C programmer talks about a `static variable', you must be careful to ask whether they mean an object with static duration, or one of the other meanings for the static keyword.

 back