CATEGORII DOCUMENTE |
Asp | Autocad | C | Dot net | Excel | Fox pro | Html | Java |
Linux | Mathcad | Photoshop | Php | Sql | Visual studio | Windows | Xml |
Now that we have seen all of the data types supported by C, we can look at the subject of initialization. C allows ordinary variables, structures, unions and arrays to be given initial values in their definitions. Old C had some strange rules about this, reflecting an unwillingness by compiler writers to work too hard. The Standard has rationalized this, and now it is possible to initialize things as and when you want.
There are basically two sorts of initialization: at compile time, and at run time. Which one you get depends on the storage duration of the thing being initialized.
Objects with static duration are declared either outside functions, or inside them with the keyword extern
or static
as part of the declaration. These can only be initialized
at compile time.
Any other object has automatic duration, and can only be initialized at run time. The two categories are mutually exclusive.
Although they are related, storage duration and linkage (see Chapter are different and should not be confused.
Compile-time initialization can only be done using constant expressions; run-time initialization can be done using any expression at all. The Old C restriction, that only simple variables (not arrays, structures or unions) could be initialized at run time, has been lifted.
There are a number of places where constant expressions must be used. The definition of what constitutes a constant expression is relatively simple.
A constant expression is evaluated by the compiler, not at
run-time. It may be used anywhere that a constant may be used. Unless it is
part of the operand of sizeof
,
it may not contain any assignment, increment or decrement operations, function
calls or comma operators; that may seem odd, but it's because sizeof
only needs to evaluate the type
of an expression, not its value.
If real numbers are evaluated at compile-time, then the Standard insists that they are evaluated with at least as much precision and range as will be used at run-time.
A more restricted form, called the integral constant expression
exists. This has integral type and only involves operands that are integer
constants, enumeration constants, character constants, sizeof
expressions and real constants
that are the immediate operands of casts. Any cast operators are only allowed
to convert arithmetic types to integral types. As with the previous note on sizeof
expressions, since they don't
have to be evaluated, just their type determined, no restrictions apply to
their contents.
The arithmetic constant expression is like the integral constant expression, but allows real constants to be used and restricts the use of casts to converting one arithmetic type to another.
The address constant is a pointer to an object that has static
storage duration or a pointer to a function. You can get these by using the &
operator or through the usual conversions of array and function names into
pointers when they are used in expressions. The operators
,
,
->
, &
(address of) and
(pointer dereference) as well as casts
of pointers can all be used in the expression as long as they don't involve
accessing the value of any object.
The various types of constants are permitted in various places; integral
constant expressions are particularly important because they are the only type
of expression that may be used to specify the size of arrays and the values in case
statement prefixes. The types of
constants that are permitted in initializer expressions are less restricted;
you are allowed to use: arithmetic constant expressions; null pointer or
address constants; an address constant for an object plus or minus an integral
constant expression. Of course it depends on the type of thing being
initialized whether or not a particular type of constant expression is
appropriate.
Here is an example using several initialized variables:
#include <stdio.h>Example 6.14
Initializing ordinary variables is easy: put = expression
after the variable name in a declaration,
and the variable is initialized to the value of the expression. As with all
objects, whether you can use any expression, or just a constant expression, depends
on its storage duration.
Initializing arrays is easy for one-dimensional arrays. Just put a list of the values you want, separated by commas, inside curly brackets. The example shows how to do it. If you don't give a size for the array, then the number of initializers will determine the size. If you do give a size, then there must be at most that many initializers in the list. Too many is an error, too few will just initialize the first elements of the array.
You could build up a string like this:
char str[] = ;but because it is so often necessary to do that, it is also permitted to use a quoted string literal to initialize an array of chars:
In that case, the null at the end of the string will also be included if there is room, or if no size was specified. Here are examples:
/* no room for the null */The example program used string literals for a different purpose: there they were being used to initialize an array of character pointers; a very different prospect.
For structures that have automatic duration, an expression of the right type can be used to initialize them, or else a bracketed list of constant expressions must be used:
#include <stdio.h>Example 6.15
Only the first member of a union can be initialized.
If a structure or union contains unnamed members, whether unnamed bitfields or padding for alignment, they are ignored in the initialization process; they don't have to be counted when you provide the initializers for the real members of the structure.
For objects that contain sub-objects within them, there are two ways of writing the initializer. It can be written out with an initializer for each member:
struct se;Example 6.16
which will assign
to x[0].a
,
to x[0].e.c
, a
to x[0].e.d
and
to x[1].a
and so on.
It is much safer to use internal braces to show what you mean, or one missed value will cause havoc.
struct se;Example 6.17
Always fully bracket initializers-that is much the safest thing to do.
It is the same for arrays as for structures:
float y[4][3] = , /* y[0][0], y[0][1], y[0][2] */Example 6.18
that gives full initialization to the first three
rows of y
. The fourth row, y[
, is uninitialized.
Unless they have an explicit initializer, all objects with static duration
are given implicit initializers-the effect is as if the constant
had been assigned to their components.
This is in fact widely used-it is an assumption made by most C programs that
external objects and internal static objects start with the value zero.
Initialization of objects with automatic duration is only guaranteed if
their compound statement is entered 'at the top'. Jumping into the middle of
one may result in the initialization not happening-this is often undesirable
and should be avoided. It is explicitly noted by the Standard with regard to switch
statements, where providing
initializers in declarations cannot
be of any use; this is because a declaration is not linguistically a
'statement' and only statements may be labelled. As a result it is not possible
for initializers in switch
statements ever to be executed, because the entry to the block containing them must be below the
declarations!
A declaration inside a function (block scope) can, using various techniques outlined in Chapter 4 and Chapter be made to refer to an object that has either external or internal linkage. If you've managed to do that, and it's not likely to happen by accident, then you can't initialize the object as part of that declaration. Here is one way of trying it:
int x; /* external linkage */Our test compiler didn't notice that one, either.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 801
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved