HPlogo HP C/HP-UX Reference Manual: Version A.05.55.02 > Chapter 2 Program Organization

Declarations

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

In general, a variable declaration has the following format:

[storage_class_specifier] [data_type] variable_name [=initial_value];

where:

storage_class_specifier

is an optional keyword.

data_type

is one of the data types described in Chapter 3 “Data Types and Declarations ”

variable_name

is a legal identifier.

initial_value

is an optional initializer for the variable.

Here are a few sample variable declarations without storage class specifiers or initial values:

int age;                         /* integer variable "age" */
int length, width;               /* abbreviated declaration of two variables*/
float ph;                        /* floating-point variable "ph" */
char a_letter;                   /* character variable "a_letter" */
int values[10];                  /* array of 10 integers named values */
enum days {mon, wed, fri};          /* enumerated variable "days" */

Typedef Declarations

The C language allows you to create your own names for data types with the typedef keyword. Syntactically, a typedef is similar to a variable declaration except that the declaration is preceded by the typedef keyword.

A typedef declaration may appear anywhere a variable declaration may appear and obeys the same scoping rules as a normal declaration. Once declared, a typedef name may be used anywhere that the type is allowed (such as in a declaration, cast operation, or sizeof operation). You can write typedef names in all uppercase so that they are not confused with variable names.

You may not include an initializer with a typedef.

The following statement makes the name FOUR_BYTE_INT synonymous with long int:

typedef long int FOUR_BYTE_INT;

The following two declarations are now identical:

long int j;
FOUR_BYTE_INT j;

Abstract Global Types

Typedefs are useful for abstracting global types that can be used throughout a program, as shown in the following structure and array declaration:

typedef struct {
    char month[4];
    int day;
    int year;
} BIRTHDAY;

typedef char A_LINE[80]; /* A_LINE is an array of
                            * 80 characters */

Improving Portability

Type definitions can be used to compensate for differences in C compilers. For example:

#if SMALL_COMPUTER
     typedef int SHORTINT;
     typedef long LONGINT;
#elif
     BIG_COMPUTER
     typedef short SHORTINT;
     typedef int LONGINT;
#endif

This is useful when writing code to run on two computers, a small computer where an int is two bytes, and a large computer where an int is four bytes. Instead of using short, long, and int, you can use SHORTINT and LONGINT and be assured that SHORTINT is two bytes and LONGINT is four bytes regardless of the machine.

Simplifying Complex Declarations

You can use typedefs to simplify complex declarations. For example:

typedef float *PTRF, ARRAYF[], FUNCF();

This declares three new types called PTRF (a pointer to a float), ARRAYF (an array of floats), and FUNCF (a function returning a float). These typedefs could then be used in declarations such as the following:

PTRF x[5];     /* a 5-element array of pointers to floats */
FUNCF z;        /* A function returning a float */

Using typedefs for Arrays

The following two examples illustrate what can happen when you mix pointers and typedefs that represent arrays. The problem with the program on the left is that ptr points to an array of 80 chars, rather than a single element of a char array. Because of scaling in pointer arithmetic, the increment operator adds 80 bytes, not one byte, to ptr.

Table 2-1 Mixing Pointers and Typedefs

WrongRight
typedef char STR[80];
STR   string, *ptr;



main()
{
   ptr = string;
   printf("ptr = %d\n", ptr);
   ptr++;
   printf("ptr = %d\n", ptr);
}

*** Run-Time Results ***

ptr = 3997696
ptr = 3997776
typedef char STR[80]; 
STR string;
char *ptr;


main()
{
   ptr = string;
   printf("ptr = %d\n", ptr);
   ptr++;
   printf("ptr = %d\n", ptr);
}

*** Run-Time Results ***

ptr = 3997696
ptr = 3997697

 

Name Spaces

All identifiers (names) in a program fall into one of four name spaces. Names in different name spaces never interfere with each other. That is, you can use the same name for an object in each of the four name spaces without these names affecting one another. Table 2-2 “Name Spaces” lists the four name spaces:

Table 2-2 Name Spaces

Name Spaces

Description

Structure, Union, and Enumeration Tags

Tag names that immediately follow these type specifiers: struct, union, and enum. These types are described in “Structure and Union Specifiers ”.

Member Names

Names of members of a structure or union.

Goto Labels

Names that mark the target of a goto statement.

Function, Variable and All Other Names

Any name that is not a member of the preceding three classes.

 

NOTE: The separate name spaces for goto labels and for each struct, union, or enum definition are part of the ANSI/ISO standard, but not part of the K&R language definition.

The following example uses the same name, overuse, in four different ways:

int main(void)
{
    int overuse;             /* normal identifier */
    struct overuse {         /* tag name */
        float overuse;       /* member name */
        char *p;
    } x;
    goto overuse;
overuse: overuse = 3;        /* label name */
}

Structure, Union, and Enum Names

Each struct, union, or enum defines its own name space, so that different declarations can have the same member names without conflict. The following is legal:

struct A {
    int x;
    float y;
};
struct B {
    int x;
    float y;
};

The members in struct A are distinct from the members in struct B.

Macro Names

Macro names do interfere with the other four name spaces. Therefore, when you specify a macro name, do not use this name in one of the other four name spaces. For example, the following program fragment is incorrect because it contains a macro named square and a label named square:

#define square(arg)  arg * arg

int main(void)
{
   ...
   square:
   ...
}

Declarations within code

HP C has added the C9x feature which allows you to declare variables and types inside a block of statements. This also allows declaration of new variables or types, such as expr_1, as shown in the for statement below:

for(expr_1;expr_2;expr_3) statement_1

This new variable or type declared in expr_1 can be used in expr_2, expr_3 and statement_1.

NOTE: The HP C/ANSI C compiler implementation of declarations within code is similar to, but not identical to, the C++ implementation of declarations within code.
© Hewlett-Packard Development Company, L.P.