HPlogo HP C/HP-UX Reference Manual: Version A.05.55.02 > Chapter 3 Data Types and Declarations

Initialization

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

An initializer is the part of a declaration that provides the initial values for the objects being declared.

Syntax

initializer ::=
assignment-expression
{initializer-list}
{initializer-list , }

initializer-list ::=
initializer
initializer-list , initializer

Description

A declarator may include an initializer that specifies the initial value for the object whose identifier is being declared.

Objects with static storage duration are initialized at load time. Objects with automatic storage duration are initialized at run-time when entering the block that contains the definition of the object. An initialization of such an object is similar to an assignment statement.

You can initialize a static object with a constant expression. You can initialize a static pointer with the address of any previously declared object of the appropriate type plus or minus a constant.

You can initialize an auto scalar object with an expression. The expression is evaluated at run-time, and the resulting value is used to initialize the object.

When initializing a scalar type, you may optionally enclose the initializer in braces. However, they are normally omitted. For example

int i = {3};

is normally specified as

int i = 3;

When initializing the members of an aggregate, the initializer is a brace-enclosed list of initializes. In the case of a structure with automatic storage duration, the initializer may be a single expression returning a type compatible with the structure. If the aggregate contains members that are aggregates, this rule applies recursively, with the following exceptions:

  • Inner braces may be optionally omitted.

  • Members that are themselves aggregates cannot be initialized with a single expression, even if the aggregate has automatic storage duration.

In ANSI mode, the initializer lists are parsed top-down; in compatibility mode, they are parsed bottom-up. For example,

int q [3] [3] [2] = {
{ 1 }
{ 2, 3 }
{ 4, 5, 6 }
};

produces the following layout:

ANSI Mode Compatibility Mode
1 0 0 0 0 0 1 0 2 3 4 5
2 3 0 0 0 0 6 0 0 0 0 0
4 5 6 0 0 0 0 0 0 0 0 0

It is advisable to either fully specify the braces, or fully elide all but the outermost braces, both for readability and ease of migration from compatibility mode to ANSI mode.

Because the compiler counts the number of specified initializes, you do not need to specify the size in array declarations. The compiler counts the initializes and that becomes the size:

int x[ ] = {1, 10, 30, 2, 45};

This declaration allocates an array of int called x with a size of five. The size is not specified in the square brackets; instead, the compiler infers it by counting the initializes.

As a special case, you can initialize an array of characters with a character string literal. If the dimension of the array of characters is not provided, the compiler counts the number of characters in the string literal to determine the size of the array. Note that the terminating \0 is also counted. For example:

char message[ ] = "hello";

This example defines an array of characters named message that contains six characters. It is identical to the following:

char message[ ] = {'h','e','l','l','o','\0'};

You can also initialize a pointer to characters with a string literal:

char *cp = "hello";

This declares the object cp as a character pointer initialized to point to the first character of the string “hello”.

It is illegal to specify more initializes in a list than are required to initialize the specified aggregate. The one exception to this rule is the initialization of an array of characters with a string literal.

char t[3] = "cat";

This initializes the array t to contain the characters c, a, and t. The trailing '\0' character is ignored.

If there are not enough initializes, the remainder of the aggregate is initialized to zero.

Some more examples include:

char *errors[ ] = {
"undefined file",
"input error",
"invalid user"
};

In this example, the array errors is an array of pointers to character (strings). The array is initialized with the starting addresses of three strings, which will be interpreted as error messages.

An array with element type compatible with wchar_t (unsigned
int
) may be initialized by a wide string literal, optionally enclosed in braces. Successive characters of the wide string literal initialize the members of the array. This includes the terminating zero-valued character, if there is room or if the array is of unknown size.

Examples

wchar_t wide_message[ ]=L"x$$z";

You initialize structures as you do any other aggregate:

struct{
int i;
unsigned u:3;
unsigned v:5;
float f;
char *p;
} s[ ] = {
{1, 07, 03, 3.5, "cats eat bats" },
{2, 2, 4, 5.0, "she said with a smile"}
};

Note that the object (s), being declared, is an array of structures without a specified dimension. The compiler counts the initializers to determine the array's dimension. In this case, the presence of two initializes implies that the dimension of s is two. You can initialize named bit-fields as you would any other member of the structure.

If the value used to initialize a bit-field is too large, it is truncated to fit in the bit-field.

For example, if the value 11 were used to initialize the 3-bit field u above, the actual value of u would be 3 (the top bit is discarded).

A struct or union with automatic storage duration can also be initialized with a single expression of the correct type.

struct SS { int y; };
extern struct SS g(void);
func()
{
struct SS z = g();
}

When initializing a union, since only one union member can be active at one time, the first member of the union is taken to be the initialized member.

The union initialization is only available in ANSI mode.

union {
int i;
float f;
unsigned u:5;
} = { 15 };

© Hewlett-Packard Development Company, L.P.