Files
oldlinux-files/Ref-docs/C/declare.html
2024-02-19 00:21:47 -05:00

1046 lines
43 KiB
HTML

<HTML><HEAD><TITLE>Declarations</TITLE></HEAD><BODY BGCOLOR="#FFFFFF">
<H1><A NAME="Declarations">Declarations</A></H1><HR>
<P><B><A HREF="#Declaration Contexts and Levels">Declaration
Contexts and Levels</A>
&#183; <A HREF="#Outer Declaration">Outer Declaration</A>
&#183; <A HREF="#Member Declaration">Member Declaration</A>
&#183; <A HREF="#Function Definition">Function Definition</A>
&#183; <A HREF="#Parameter Declaration">Parameter Declaration</A>
&#183; <A HREF="#Block Declaration">Block Declaration</A>
&#183; <A HREF="#Prototype Declaration">Prototype Declaration</A>
&#183; <A HREF="#Type-Name Declaration">Type-Name Declaration</A>
&#183; <A HREF="#Declaration Levels">Declaration Levels</A>
&#183; <A HREF="#Visibility and Name Spaces">Visibility
and Name Spaces</A>
&#183; <A HREF="#Name Spaces">Name Spaces</A>
&#183; <A HREF="#Scope">Scope</A>
&#183; <A HREF="#Linkage and Multiple Declarations">Linkage
and Multiple Declarations</A>
&#183; <A HREF="#Linkage">Linkage</A>
&#183; <A HREF="#Tags">Tags</A>
&#183; <A HREF="#Type Definition">Type Definition</A>
&#183; <A HREF="#Object Declaration">Object Declaration</A>
&#183; <A HREF="#Function Declaration">Function Declaration</A>
&#183; <A HREF="#Reading Declarations">Reading Declarations</A>
&#183; <A HREF="#Object Initializers">Object Initializers</A>
</B></P>
<HR>
<P>A translation unit consists of one or more declarations, each
of which can:</P>
<UL>
<LI>give meaning to a name that you create for use over some portion
of a translation unit</LI>
<LI>allocate storage for an object and (possibly) define its initial
contents</LI>
<LI>define the behavior of a function</LI>
<LI>specify a type</LI>
</UL>
<P>Declarations can contain other declarations in turn.</P>
<P>This document describes how to use declarations to construct
a C program. It describes how to create names and how to use the same
name for distinct purposes. It also shows how to write object initializers
to specify the initial values stored in objects. The behavior of
<A HREF="function.html" tppabs="http://ccs.ucsd.edu/c/function.html">functions</A> is described separately.</P>
<H2><A NAME="Declaration Contexts and Levels">Declaration
Contexts and Levels</A></H2>
<P>You can write declarations in different <B>contexts</B>.
The syntax of an arbitrary declaration (other than a function definition)
is:</P>
<P><IMG SRC="decl.gif" tppabs="http://ccs.ucsd.edu/c/gif/decl.gif"></P>
<P>The presentation that follows shows graphically
how each context restricts the declarations that you can write, by
eliminating from this syntax diagram those parts that are not permitted
in a given context. It also describes when you must write
a name within the declarator part of a declaration and when you must
not.</P>
<P>Here is a sampler of all
possible declaration contexts:</P>
<PRE>
struct stack { <B><A HREF="#Outer Declaration">outer declaration</A></B>
int top, a[100]; <B><A HREF="#Member Declaration">member declaration</A></B>
} stk = {0};
void push(val) <B><A HREF="#Function Declaration">function definition</A></B>
int val; <B><A HREF="#Parameter Declaration">parameter declaration</A></B>
{
extern void oflo( <B><A HREF="#Block Declaration">block declaration</A></B>
char *mesg); <B><A HREF="#Prototype Declaration">prototype declaration</A></B>
if (stk.top &lt; sizeof a /
sizeof (int)) <B><A HREF="#Type-Name Declaration">type-name declaration</A></B>
stk.a[stk.top++] = val;
else
oflo("stack overflow");
}</PRE>
<H3> <A NAME="Outer Declaration">Outer Declaration</A></H3>
<P>You write an <B>outer declaration</B> as one of the declarations
that make up a translation unit.
An outer declaration is one that is not contained within
another declaration or function definition:</P>
<P><IMG SRC="outer_d.gif" tppabs="http://ccs.ucsd.edu/c/gif/outer_d.gif"></P>
<P>You can omit the declarator only for a structure, union, or
enumeration declaration that declares a tag. You must write a name
within the declarator of any other outer declarator.</P>
<H3><A NAME="Member Declaration">Member Declaration</A></H3>
<P>You write a <B>member declaration</B> to declare members of
a structure or union, as part of another declaration.</P>
<P><IMG SRC="member_d.gif" tppabs="http://ccs.ucsd.edu/c/gif/member_d.gif"></P>
<P>A bitfield can be <B>unnamed</B>. If the declarator
is for a bitfield that has zero size, do not write a name within the
declarator. If the declarator is for a bitfield that has nonzero size,
then you can optionally write a name; otherwise, you <I>must</I> write
a name.</P>
<H3><A NAME="Function Definition">Function Definition</A></H3>
<P>You write a <B>function definition</B> as one of the declarations
that make up a translation unit. You cannot write a function definition
within another declaration or function definition.</P>
<P><IMG SRC="fun_def.gif" tppabs="http://ccs.ucsd.edu/c/gif/fun_def.gif"></P>
<P>This is the only context where you can omit both the storage
class and any type part. You must write a name within the declarator.</P>
<H3><A NAME="Parameter Declaration">Parameter Declaration</A></H3>
<P>You write a <B>parameter declaration</B> as part of a function
definition whose function declarator contains a list of parameter
names. You must write a parameter name within the declarator.</P>
<P><IMG SRC="param_d.gif" tppabs="http://ccs.ucsd.edu/c/gif/param_d.gif"></P>
<H3><A NAME="Block Declaration">Block Declaration</A></H3>
<P>You write a <B>block declaration</B> as one of the declarations
that begin a block within a function definition.</P>
<P><IMG SRC="block_d.gif" tppabs="http://ccs.ucsd.edu/c/gif/block_d.gif"></P>
<P>You can omit the declarator only for a structure, union, or
enumeration declaration that declares a tag. Otherwise, you must write
a name within the declarator.</P>
<H3><A NAME="Prototype Declaration">Prototype Declaration</A></H3>
<P>You write a <B>prototype declaration</B> within a declarator
as part of a function decoration to declare a function parameter.</P>
<P><IMG SRC="proto_d.gif" tppabs="http://ccs.ucsd.edu/c/gif/proto_d.gif"></P>
<P>If the prototype declaration declares a parameter for a function
that you are defining (it is part of a function definition), then
you must write a name within the declarator. Otherwise, you can omit
the name.</P>
<H3><A NAME="Type-Name Declaration">Type-Name Declaration</A></H3>
<P>You write a <B>type-name declaration</B> within an expression,
eihher as a
<A HREF="express.html#Type Cast" tppabs="http://ccs.ucsd.edu/c/express.html#Type Cast">type cast</A>
operator or following the
<A HREF="express.html#sizeof operator" tppabs="http://ccs.ucsd.edu/c/express.html#sizeof operator">sizeof</A> operator. Do
not write a name within the declarator.</P>
<P><IMG SRC="type_d.gif" tppabs="http://ccs.ucsd.edu/c/gif/type_d.gif"></P>
<H3><A NAME="Declaration Levels">Declaration Levels</A></H3>
<P>You use
<A HREF="#Member Declaration">member declarations</A> and
<A HREF="#Type-Name Declaration">type-name declarations</A> only
to specify type information. You declare the functions and objects
that make up the program in the remaining five contexts shown above.
These contexts reside at three <B>declaration levels</B>:</P>
<UL>
<LI><B><A NAME="file-level declaration">File-level declarations</A></B>
are the <A HREF="#Outer Declaration">outer declarations</A> and
<A HREF="#Function Definition">function definitions</A>
that make up the translation unit.</LI>
<LI><B><A NAME="parameter-level declaration">Parameter-level
declarations</A></B> are
<A HREF="#Parameter Declaration">parameter</A> and
<A HREF="#Prototype Declaration">prototype declarations</A>
that declare parameters for functions.</LI>
<LI><B><A NAME="block-level declaration">Block-level
declarations</A></B> are
<A HREF="#Block Declaration">block declarations</A>.</LI>
</UL>
<P>How the translator interprets a declaration that you write depends
on the level at which you write it. In particular, the meaning of
a storage class keyword that you write (or the absence of a storage
class keyword) differs considerably among the declaration levels.</P>
<H2><A NAME="Visibility and Name Spaces">Visibility
and Name Spaces</A></H2>
<P>You use names when you declare or define different entities
in a program (possibly by including a standard header). The entities
that have names are:</P>
<UL>
<LI><B><A HREF="preproc.html#macros" tppabs="http://ccs.ucsd.edu/c/preproc.html#macros">macros</A></B> --
which the translator predefines or which
the program defines with a
<A HREF="preproc.html#Define Directives" tppabs="http://ccs.ucsd.edu/c/preproc.html#Define Directives"><I>define</I> directive</A></LI>
<LI><B><A HREF="syntax.html#keyword" tppabs="http://ccs.ucsd.edu/c/syntax.html#keyword">keywords</A></B> --
which the translator predefines</LI>
<LI><B><A HREF="#Function Declaration">functions</A></B> and
<B><A HREF="#Object Declaration">objects</A></B> -- which the program
declares, and which either the Standard C library or the program defines</LI>
<LI><B><A HREF="#Type Definition">type definitions</A></B> and
<B><A HREF="types.html#enumeration constants" tppabs="http://ccs.ucsd.edu/c/types.html#enumeration constants">enumeration constants</A></B>
-- which the program defines</LI>
<LI><B><A HREF="#Tags">tags</A></B> for enumerations, structures,
and unions -- which the program declares and can also define</LI>
<LI><B><A HREF="function.html#Goto Label" tppabs="http://ccs.ucsd.edu/c/function.html#Goto Label"><I>goto</I> labels</A></B> --
which the program defines</LI>
</UL>
<P>The program can declare or define some of these entities by including
<A HREF="lib_over.html#standard headers" tppabs="http://ccs.ucsd.edu/c/lib_over.html#standard headers">standard headers</A>.
The program can
<A HREF="function.html#implicit declaration" tppabs="http://ccs.ucsd.edu/c/function.html#implicit declaration">implicitly declare</A>
a function by calling the function within an expression.</P>
<P>Each entity is
<B><A NAME="visibility">visible</A></B> over some region of the program
text. You refer to a visible entity by writing its name. A macro,
for example, is visible from the
<A HREF="preproc.html#define directive" tppabs="http://ccs.ucsd.edu/c/preproc.html#define directive"><I>define</I> directive</A>
that defines it to any
<A HREF="preproc.html#undef directive" tppabs="http://ccs.ucsd.edu/c/preproc.html#undef directive"><I>undef</I> directive</A>
that removes the definition or to
the end of the translation unit. An object that you declare within
a block is visible from where you declare it to the end of the block
(except where it is masked, as described below).</P>
<H3><A NAME="Name Spaces">Name Spaces</A></H3>
<P>You can sometimes
<B><A NAME="masking">mask</A></B> an entity by giving another meaning
to the same name. An object that you declare within an inner block,
for example, can mask a declaration in a containing block (until the
end of the inner block). You can use an existing name for a new entity
only if its name occupies a different name space from the entity it
masks. You can specify an open-ended set of name spaces.</P>
<P>The following diagram shows
the relationship between various name spaces:</P>
<P><IMG SRC="namesp.gif" tppabs="http://ccs.ucsd.edu/c/gif/namesp.gif"></P>
<P>Each box in this diagram is a separate name space.
You can use a name only
one way within a given name space. The diagram shows, for example,
that within a block you cannot use the same name both as a structure
tag and as a union tag.</P>
<PRE>
union x {int i; float f;};
struct x {... }; <B>INVALID: same name space</B></PRE>
<P>Each box in this diagram masks any boxes to its right. If the
translator can interpret a name as designating an entity within a
given box, then the same name in any box to its right is not visible.
If you define a macro without parameters, for example, then the translator
will always take the name as the name of the macro. The macro definition
masks any other meaning.</P>
<PRE>
extern int neg(int x);
#define neg(x) (-(x))
y = neg(i + j); <B>macro masks function</B></PRE>
<P>You introduce two new name spaces with every block that you
write. One name space includes all functions, objects, type definitions,
and enumeration constants that you declare or define within the block.
The other name space includes all enumeration, structure, and union
tags that you define within the block. You can also introduce a new
structure or union tag within a block before you define it by writing
a declaration without a declarator, as in:</P>
<PRE>
{ <B>new block</B>
struct x; <B>new meaning for x</B>
struct y {
struct x *px; <B>px points to new x</B></PRE>
<P>A structure or union declaration with only a tag (and no definition
or declarator) masks any tag name declared in a containing block.</P>
<P>The outermost block of a function definition includes in its
name space all the parameters for the function, as object declarations.
The name spaces for a block end with the end of the block.</P>
<P>You introduce a new
<A HREF="function.html#Goto Label" tppabs="http://ccs.ucsd.edu/c/function.html#Goto Label"><I>goto</I> label</A>
name space with every function definition you write.
Each <I>goto</I> label name space ends
with its function definition.</P>
<P>You introduce a new member name space with every structure or
union whose content you define. You identify a member name space by
the type of left operand that you write for a member selection operator,
as in <CODE>x.y</CODE> or <CODE>p-&gt;y</CODE>.
A member name space ends with the
end of the block in which you declare it.</P>
<H3><A NAME="Scope">Scope</A></H3>
<P>The <B>scope</B> of a name that you declare or define is the
region of the program over which the name retains its declared or
defined meaning. A name is
<A HREF="#visibility">visible</A> over its scope except where it is
<A HREF="#masking">masked</A>:</P>
<UL>
<LI>A <A HREF="#file-level declaration">file-level declaration</A>
is in scope from the point where it
is complete to the end of the translation unit.</LI>
<LI>A <A HREF="#parameter-level declaration">parameter-level declaration</A>
is in scope from the point where
it is declared in the function definition to the end of the outermost
block of the function definition. (If there is no function definition,
the scope of a parameter-level declaration ends with the declaration.)</LI>
<LI>A <A HREF="#block-level declaration">block-level declaration</A>
is in scope from the point where it
is complete to the end of the block.</LI>
</UL>
<P>A macro name is in scope from the point where it is defined (by a
<A HREF="preproc.html#define directive" tppabs="http://ccs.ucsd.edu/c/preproc.html#define directive"><I>define</I> directive</A>)
to the point where its definition is removed (by an
<A HREF="preproc.html#undef directive" tppabs="http://ccs.ucsd.edu/c/preproc.html#undef directive"><I>undef</I> directive</A>, if any).
You cannot mask a macro name.</P>
<H2><A NAME="Linkage and Multiple Declarations">Linkage
and Multiple Declarations</A></H2>
<P>You can sometimes use the same name to refer to the same entity
in multiple declarations. For functions and objects, you write declarations
that specify various kinds of
<A HREF="#Linkage">linkage</A> for the name you declare.
By using linkage, you can write multiple declarations:</P>
<UL>
<LI>for the same name in the same name space</LI>
<LI>for the same name in different name spaces</LI>
</UL>
<P>In either of these two cases, you can have the declarations
refer to the same function or object.</P>
<P>You can use the same enumeration, structure, or union tag in
multiple declarations to refer to a common type. Similarly, you can
use a type definition to define an arbitrary type in one declaration
and use that type in other declarations.</P>
<H3><A NAME="Linkage">Linkage</A></H3>
<P>A declaration specifies the <B>linkage</B> of a name. Linkage
determines whether the same name declared in different declarations
refers to the same function or object. There are three kinds of linkage:</P>
<UL>
<LI>A name with
<B><A NAME="external linkage">external linkage</A></B>
designates the same function
or object as does any other declaration for the same name with external
linkage. The two declarations can be in the same translation unit
or in different translation units. Different names that you write
with external linkage must differ (other than in case) within the
first six characters.</LI>
<LI>A name with
<B><A NAME="internal linkage">internal linkage</A></B>
designates the same function
or object as does any other declaration for the same name with internal
linkage in the same translation unit.</LI>
<LI>A name with
<B><A NAME="no linkage">no linkage</A></B>
designates a unique object or a type definition;
do not declare the same name again in the same name space.</LI>
</UL>
<P>The names of functions always have either external or internal
linkage.</P>
<P>There are separate rules for determining linkage of
<A HREF="#Object Declaration">objects</A> and
<A HREF="#Function Declaration">functions</A>.
In either case, however, do not declare
the same name with both internal linkage and external linkage in the
same translation unit.</P>
<P>Whenever two declarations designate the same function or object,
the types specified in the two declarations must be compatible. If
two such declarations are in the same name space, the resulting type
for the second declaration is the
<A HREF="types.html#Compatible and Composite Types" tppabs="http://ccs.ucsd.edu/c/types.html#Compatible and Composite Types">composite type</A>.</P>
<P>For example, a valid combination of declarations is:</P>
<PRE>
extern int a[]; <B>external linkage</B>
extern int a[10]; <B>type is compatible</B></PRE>
<H3><A NAME="Tags">Tags</A></H3>
<P>You use enumeration, structure, and union <B>tags</B> to designate
the same integer, structure, or union type in multiple declarations.
You provide a definition for the type (enclosed in braces) in no more
than one of the declarations. You can use a structure or union tag
(but not an enumeration tag) in a declaration before you define the
type, to designate an
<A HREF="types.html#incomplete structure types" tppabs="http://ccs.ucsd.edu/c/types.html#incomplete structure types">incomplete structure</A> or
<A HREF="types.html#incomplete union types" tppabs="http://ccs.ucsd.edu/c/types.html#incomplete union types">incomplete union</A> type.
When you later provide a definition
for the incomplete structure or union type, it must be in the same
<A HREF="#Name Spaces">name space</A>.</P>
<P>For example:</P>
<PRE>
struct node { <B>begin definition of node</B>
int type, value;
struct node *L, *R; <B>valid: although node incomplete</B>
} *root = NULL; <B>node now complete</B></PRE>
<P>Here, a declaration that refers to the structure whose tag is
<CODE>node</CODE> appears before the structure type is complete. This is
the only way to declare a structure that refers to itself
in its definition.</P>
<H3><A NAME="Type Definition">Type Definition</A></H3>
<P>You use type definitions to designate the same arbitrary type
in multiple declarations. A type definition is not a new type; it
is a synonym for the type you specify when you write the type definition.</P>
<P>For example:</P>
<PRE>
typedef int I, AI[], *PI;
extern int i, ai[10], *pi;
extern I i; <B>valid: compatible type</B>
extern AI ai; <B>valid: compatible type</B>
extern PI pi; <B>valid: compatible type</B></PRE>
<P>You can write any type in a type definition. You cannot, however,
use a type definition in a function definition if the parameter list
for the function being defined is specified by the type definition.</P>
<P>For example:</P>
<PRE>
typedef void VOID; <B>valid type definition</B>
typedef VOID VF(int x); <B>valid type definition</B>
VF *pf; <B>valid use of type definition</B>
VF f { <B>INVALID use of type definition</B></PRE>
<P>The parameter list for a function must appear explicitly as
a function decoration in the declarator part of a function definition,
as in:</P>
<PRE>
VOID f(int x) { <B>valid use of type definition</B></PRE>
<P>A type definition behaves exactly like its synonym when the
translator compares types. (The type definition and its synonym are
<A HREF="types.html#Compatible and Composite Types" tppabs="http://ccs.ucsd.edu/c/types.html#Compatible and Composite Types">compatible</A>.)</P>
<H2><A NAME="Object Declaration">Object Declaration</A></H2>
<P>You declare the objects that the program manipulates at
<A HREF="#file-level declaration">file level</A>, at
<A HREF="#parameter-level declaration">parameter level</A>
(within a function definition), or at
<A HREF="#block-level declaration">block level</A>.
The storage class keyword you write (if any) determines
several properties of an object declaration. The same storage class
can have different meanings at the three declaration levels.</P>
<P>The properties you specify by writing a given storage class
at a given declaration level are
<A HREF="#Linkage">linkage</A>,
<A HREF="#storage duration">storage duration</A>,
<A HREF="#forms of initialization">form of initialization</A>, and
<A HREF="#object definition status">object definition status</A>.
An object declaration can specify that a name has:</P>
<UL>
<LI><A HREF="#external linkage">external linkage</A></LI>
<LI><A HREF="#internal linkage">internal linkage</A></LI>
<LI><A HREF="#no linkage">no linkage</A></LI>
</UL>
<P>Some declarations accept the
<B><A NAME="previous linkage">previous linkage</A></B> of a declaration
that is visible at file level for the same name (with external or
internal linkage). If such a declaration is not visible, then the
previous linkage is taken to be external linkage.</P>
<P>An object declaration can specify that the declared object has
one of two <B><A NAME="storage duration">storage durations</A></B>:</P>
<UL>
<LI>An object with
<B><A NAME="static duration">static duration</A></B> exists from
<A HREF="lib_over.html#program startup" tppabs="http://ccs.ucsd.edu/c/lib_over.html#program startup">program startup</A> to
<A HREF="lib_over.html#program termination" tppabs="http://ccs.ucsd.edu/c/lib_over.html#program termination">program termination</A>.
It assumes its initial value prior to program startup.</LI>
<LI>An object with
<B><A NAME="dynamic duration">dynamic duration</A></B> exists from
the time that control enters the block
in which you declare the object to the
time that control leaves the block. If you specify an initializer,
then the initializer is evaluated and its value is stored in the object
when control enters the block. (A
<A HREF="function.html#Goto Statement" tppabs="http://ccs.ucsd.edu/c/function.html#Goto Statement"><I>goto</I></A> or
<A HREF="function.html#Switch Statement" tppabs="http://ccs.ucsd.edu/c/function.html#Switch Statement"><I>switch</I> statement</A>
that transfers control to a
<A HREF="function.html#Case Label" tppabs="http://ccs.ucsd.edu/c/function.html#Case Label"><I>case</I></A>,
<A HREF="function.html#Default Label" tppabs="http://ccs.ucsd.edu/c/function.html#Default Label"><I>default</I></A>, or
<A HREF="function.html#Goto Label" tppabs="http://ccs.ucsd.edu/c/function.html#Goto Label"><I>goto</I> label</A>
within the block allocates storage for objects with dynamic
duration but it does not store any initial values.) A function that
calls itself recursively, either directly or indirectly, allocates
a separate version of an object with dynamic duration for each activation
of the block that declares the object.</LI>
</UL>
<P>A type definition for an object type has
<B><A NAME="no duration">no duration</A></B>
because duration has no meaning in this case.</P>
<P>An object declaration can permit one of two
<B><A NAME="forms of initialization">forms of initialization</A></B>:</P>
<UL>
<LI>A
<B><A NAME="static initializer">static initializer</A></B>
contains only expressions that the translator can
<A HREF="express.html#Classes of Expressions" tppabs="http://ccs.ucsd.edu/c/express.html#Classes of Expressions">evaluate</A>
prior to program startup.</LI>
<LI>A
<B><A NAME="dynamic initializer">dynamic initializer</A></B>
can contain an expression that
the program evaluates when it executes, called an
<A HREF="express.html#rvalue expression" tppabs="http://ccs.ucsd.edu/c/express.html#rvalue expression">rvalue expression</A>.
If you write a list of expressions
(separated by commas and enclosed in braces) to
<A HREF="#Object Initializers">initialize an object</A>
of array, structure, or union type,
then each expression must be a valid static initializer, even within
a dynamic initializer.</LI>
</UL>
<P>You must write
<B><A NAME="no initializer">no initializer</A></B> in some cases.</P>
<P>Each of the four kinds of
<B><A NAME="object definition status">object definition status</A></B>
of a declaration
determines whether the declaration causes storage for an object to
be allocated:</P>
<UL>
<LI>If an object declaration is an
<B><A NAME="object definition">object definition</A></B>, then it causes
storage to be allocated for the object.</LI>
<LI>If an object declaration is a
<B><A NAME="tentative declaration">tentative definition</A></B> and
you write no definition for the same object later in the translation
unit, then the translator allocates storage for the object at the
end of the translation unit. The initial value in this case is all
zeros.</LI>
<LI>If an object declaration is a
<B><A HREF="#Type Definition">type definition</A></B>, then it
only defines a type. (No object exists.)</LI>
<LI>If an object declaration is <B>not a definition</B> and you
do not write an initializer, then the declaration does not allocate
storage for the object. If you write any expression that refers to
the object, then you must provide a definition (in the same or another
translation unit) that designates the same object.</LI>
</UL>
<P>The following table summarizes the effect
of each storage class at each declaration level on object declarations:</P>
<PRE>
<B>Storage File-Level Parameter-Level Block-Level
Class Declaration Declaration Declaration</B>
<B>none</B> external linkage no linkage no linkage
static duration dynamic duration dynamic duration
static initializer no initializer dynamic initializer
tentative definition definition definition
auto -- -- no linkage
dynamic duration
dynamic initializer
definition
extern previous linkage -- previous linkage
static duration static duration
static initializer no initializer
not a definition not a definition
register -- no linkage no linkage
dynamic duration dynamic duration
no initializer dynamic initializer
definition definition
static internal linkage -- no linkage
static duration static duration
static initializer static initializer
tentative definition definition
typedef no linkage -- no linkage
no duration no duration
no initializer no initializer
type definition type definition</PRE>
<P>The table specifies the definition status assuming that you do not
write an initializer. In all cases, if you write an initializer (where
permitted), then the declaration allocates storage for the object.
(It is a definition.) For example, the following two declarations
both name the same object:</P>
<PRE>
static int abc; <B>internal linkage, tentative definition</B>
extern int abc; <B>previous linkage, no definition</B></PRE>
<H2><A NAME="Function Declaration">Function Declaration</A></H2>
<P>You declare the functions that a program calls at
<A HREF="#file-level declaration">file level</A> or at
<A HREF="#block-level declaration">block level</A>.
The translator alters any declaration you write
at parameter level with type <I>function returning T</I> to type <I>pointer
to function returning T,</I> which is an object type.</P>
<P>The properties you specify by writing a given storage class
at a given declaration level are
<A HREF="#Linkage">linkage</A> and
<A HREF="#function definition status">function definition status</A>.
A function declaration can specify that a name has:</P>
<UL>
<LI><A HREF="#internal linkage">internal linkage</A></LI>
<LI><A HREF="#no linkage">no linkage</A></LI>
</UL>
<P>Some declarations accept the
<A HREF="#previous linkage">previous linkage</A> of a declaration
that is visible at file level for the same name (with external or
internal linkage). If such a declaration is not visible, then the
previous linkage is taken to be
<A HREF="#external linkage">external linkage</A></P>
<P>The
<B><A NAME="function definition status">function definition status</A></B>
of a declaration determines whether
you can write a function definition in that context. You have one
of three possibilities:</P>
<UL>
<LI>You <B>can define</B> a function.</LI>
<LI>You <B>cannot define</B> a function.</LI>
<LI>You provide a
<B><A HREF="#Type Definition">type definition</A></B>.
(No function exists.)</LI>
</UL>
<P>The following table summarizes the effect
of each storage class, at each declaration level,
on function declarations:</P>
<PRE>
<B>Storage File-Level Parameter-Level Block-Level
Class Declaration Declaration Declaration</B>
<B>none</B> previous linkage (becomes pointer previous linkage
can define to function) cannot define
auto -- -- --
extern previous linkage -- previous linkage
can define cannot define
register -- (becomes pointer --
to function)
static internal linkage -- --
can define
typedef no linkage -- no linkage
type definition type definition</PRE>
<P>For example, the following declarations both name the same function:</P>
<PRE>
static int f(void); <B>internal linkage</B>
extern int f(void); <B>previous linkage</B></PRE>
<H2><A NAME="Reading Declarations">Reading Declarations</A></H2>
<P>Reading a declaration is not always easy. Proceed with caution
any time:</P>
<UL>
<LI>you omit the name</LI>
<LI>you write parentheses in the declarator</LI>
<LI>you give a new meaning to a name that is visible
as a type definition</LI>
</UL>
<P>The following provides some simple guidelines for writing and
reading complex declarations.</P>
<P>When you write a declaration, avoid redundant parentheses. In
particular, never write parentheses around a name,
as in <CODE>int (x)</CODE>, because it is easy
for you or others to misread the parenthesized
name as a parameter list, and the type changes if you omit the name.</P>
<P>You <I>must</I> omit the name when you write a
<A HREF="express.html#Type Cast" tppabs="http://ccs.ucsd.edu/c/express.html#Type Cast"><I>type cast</I> operator</A>.
You <I>can</I> omit the name in a declarator when you write
a function parameter declaration that is not part of a function definition.
If you omit the name in the example above,
you get <CODE>int ()</CODE>,
which specifies type <I>function returning int,</I> not type <I>int.</I></P>
<P>Avoid writing a declaration that
<A HREF="#masking">masks</A> a type definition. If
you must mask a type definition, write at least one type part in the
masking declaration that is not a type qualifier. The translator assumes
that a name visible as a type definition is always a type part if
that is a valid interpretation of the source text, even if another
interpretation is also valid.</P>
<P>For example:</P>
<PRE>
typedef char Small;
int g(short Small); <B>valid: Small has new meaning</B>
int f(Small) <B>Small taken as type definition</B>
short Small; <B>INVALID: not a parameter name</B></PRE>
<P>To read a declaration, you must first replace the name if it
has been omitted. You determine where to write the name by reading
the declaration from left to right until you encounter:</P>
<UL>
<LI>the end of the declaration</LI>
<LI>a right parenthesis</LI>
<LI>a left bracket</LI>
<LI>a left parenthesis followed by either a type part or a right
parenthesis</LI>
</UL>
<P>You write the name immediately to the left of this point.</P>
<P>For example:</P>
<PRE>
int <B>becomes</B> int x
void (*)() <B>becomes</B> void (*x)()
char [] <B>becomes</B> char x[]
long () <B>becomes</B> long x()</PRE>
<P>You read a complex declaration by first locating the name (using
the previous rules). Then you:</P>
<OL>
<LI>Read the array or function decorations from left to right, beginning
with the name, until you come to the end of the declarator or to a
right parenthesis.</LI>
<LI>Read the pointer decorations from right to left, beginning back
at the name, until you come to the beginning of the declarator, to
a type part, or to a left parenthesis.</LI>
<LI>If you encounter a left parenthesis, repeat the first two steps
(treating the parenthesized declarator as if it were the name).</LI>
<LI>Read the type specified by the type parts.</LI>
</OL>
<P>The following diagram can also help:</P>
<PRE>
<B>d7 d6 ( d4 d3 NAME d1 d2 ) d5</B></PRE>
<P>Read the decorations in increasing numeric order, beginning
with <CODE><B>d1</B></CODE> and ending with the type parts
(<CODE><B>d7</B></CODE>). It is often
sufficient simply to remember that, in the absence of parentheses
(or within a pair of grouping parentheses), you read the pointer decorations
as the last part of the type.</P>
<P>For example:</P>
<PRE>
int *fpi(void) <B>is function returning pointer to int</B>
int (*pfi)(void) <B>is pointer to function returning int</B>
unsigned int *(* const *name[5][10])(void)
<B>is array with 5 elements of
array with 10 elements of
pointer to
pointer which is constant to
function (no parameters) returning
pointer to
unsigned int</B></PRE>
<H2><A NAME="Object Initializers">Object Initializers</A></H2>
<P>You can specify an initial value for an
<A HREF="#Object Declaration">object</A> by writing an
<B>initializer</B>. The type of the object
and the declaration context constrain
how you write an initializer.</P>
<P>You initialize an object with static duration by writing a
<B><A NAME="static initializer">static initializer</A></B>.
A static initializer for an object with scalar type
consists of a single expression (possibly enclosed in braces) that
the translator can
<A HREF="express.html#Classes of Expressions" tppabs="http://ccs.ucsd.edu/c/express.html#Classes of Expressions">evaluate</A> prior to
<A HREF="lib_over.html#program startup" tppabs="http://ccs.ucsd.edu/c/lib_over.html#program startup">program startup</A>.
A static initializer for an object with array, structure,
or union type consists of a list
of one or more initializers separated by commas and enclosed in braces.</P>
<P>For example:</P>
<PRE>
extern char *first = NULL;
static short February[4] = {29, 28, 28, 28};</PRE>
<P>You initialize an object with dynamic duration by writing a
<B><A NAME="dynamic initializer">dynamic initializer</A></B>.
For other than array types, any
<A HREF="express.html#rvalue expression" tppabs="http://ccs.ucsd.edu/c/express.html#rvalue expression">rvalue expression</A> that is
<A HREF="types.html#assignment compatible" tppabs="http://ccs.ucsd.edu/c/types.html#assignment compatible">assignment compatible</A>
with the type of the object
can serve as a dynamic initializer. You can also write a dynamic initializer
in the same form as a static initializer.</P>
<P>For example:</P>
<PRE>
auto int bias =
{RAND_MAX/2}; <B>static form initializer</B>
auto int val =
rand() &lt; bias; <B>dynamic form initializer</B></PRE>
<P>The initializers that you write within a list separated by commas are
<B><A NAME="inner initializer">inner initializers</A></B>.
You write an inner initializer the
same way you write a static initializer, except that you can omit
the outermost braces:</P>
<UL>
<LI>For an object of structure type, the list of inner initializers
you write initializes each member of the structure in turn, beginning
with the first. The translator skips unnamed bitfields, which you
cannot initialize.</LI>
<LI>For an object of union type, you can initialize only the first
member of the union.</LI>
<LI>For an object of array type, the list of inner initializers
you write initializes each element of the array in turn, beginning
with element number zero. The last array subscript varies most rapidly.</LI>
</UL>
<P>Some examples are:</P>
<PRE>
struct complex {
float real, imag;
} neg_one = {-1, 0}; <B>values for real and imag</B>
union {
struct complex *p;
float value;
} val_ptr =
{&amp;neg_one}; <B>initializes pointer member</B>
int a23[2][3] =
{{00, 01, 02}, <B>all braces present</B>
{10, 11, 12}}; <B>on inner initializers</B>
int a32[3][2] =
{00, 01, <B>braces omitted</B>
10, 11, <B>on inner initializers</B>
20, 21};</PRE>
<P>If you do not provide as many initializers as there are members
or elements to initialize, the translator initializes any remaining
members or elements to the value zero. Do not provide excess initializers.
You can initialize an object of incomplete array type, in which case
the number of element initializers you write determines the repetition
count and completes the array type.</P>
<P>For example:</P>
<PRE>
double matrix[10][10] =
{1.0}; <B>rest set to 0</B>
int ro[] = {1, 5, 10,
50, 100, 500}; <B>6 elements</B></PRE>
<P>You can initialize an array of any character type by writing
a string literal, or an array of <CODE>wchar_t</CODE>
by writing a wide character string literal,
as shorthand for a sequence of character constants.
The translator retains the terminating null character only when you
initialize an object of incomplete array type. (An object of complete
array type is padded as needed with trailing zero initializers.)</P>
<P>For example:</P>
<PRE>
char fail[6] = "fail"; <B>same as</B> {'f', 'a', 'i', 'l', 0, 0}
char bad[] = "bad"; <B>same as</B> {'b', 'a', 'd', '\0'}
wchar_t hai[3] = L"hai"; <B>same as</B> {L'h', L'a', L'i'}</PRE>
<P>But note:</P>
<PRE>
wchar_t hai[3] = {L'h', L'a', L'i',
'\0'}; <B>INVALID</B></PRE>
<P>The following table summarizes the various
constraints on initializer expressions or initializer lists, depending
on context and the type of the object:</P>
<PRE>
<B> Dynamic Static Inner
Type Initializer Initializer Initializer</B>
arithmetic { arithmetic { arithmetic { arithmetic
rvalue } constant constant
expression } expression }
arithmetic arithmetic arithmetic
rvalue constant constant
expression expression
pointer { assignment- { address { address
compatible constant constant
rvalue } expression } expression }
assignment- address address
compatible constant constant
rvalue expression expression
structure { inner { inner { inner
initializer list initializer list initializer list
for members } for members } for members }
compatible inner
structure initializer list
rvalue for members
union { inner { inner { inner
initializer list initializer list initializer list
for first for first for first
member } member } member }
compatible inner
union initializer list
rvalue for first
member
array { inner { inner { inner
initializer list initializer list initializer list
for elements } for elements } for elements }
inner
initializer list
for elements
array of { "..." } { "..." } { "..." }
character "..." "..." "..."
array of { L"..." } { L"..." } { L"..." }
wchar_t L"..." L"..." L".."</PRE>
<P>This table shows you, for example,
that you can write an arbitrary arithmetic
<A HREF="express.html#rvalue expression" tppabs="http://ccs.ucsd.edu/c/express.html#rvalue expression">rvalue expression</A> as the
initializer for an object with arithmetic type and dynamic duration.
You can write an
<A HREF="express.html#arithmetic constant expression" tppabs="http://ccs.ucsd.edu/c/express.html#arithmetic constant expression">arithmetic
constant expression</A>, with or without braces,
anywhere you initialize an object with arithmetic type.</P>
<P>The table also shows you that you can initialize the elements
of an object of array type, in any context, by writing a list of initializers
in braces. You can omit the braces only for a string literal initializer
or for a list you write as an inner initializer for some containing
initializer.</P>
<HR>
<P>See also the
<B><A HREF="index.html#Table of Contents" tppabs="http://ccs.ucsd.edu/c/index.html#Table of Contents">Table of Contents</A></B> and the
<B><A HREF="_index.html" tppabs="http://ccs.ucsd.edu/c/_index.html">Index</A></B>.</P>
<P><I>
<A HREF="crit_pb.html" tppabs="http://ccs.ucsd.edu/c/crit_pb.html">Copyright</A> &#169; 1989-1996
by P.J. Plauger and Jim Brodie. All rights reserved.</I></P>
</BODY></HTML>