A 10 External Declarations
This page is a generated reference surface for selective reading. It exists to keep the learner apps guide-first while still preserving source access.
Learning objectives
- Explain the main ideas and vocabulary in A 10 External Declarations.
- Work through the source examples for A 10 External Declarations without depending on raw chunk order.
- Use A 10 External Declarations as selective reference when learner modules point back to The C Programming Language.
Prerequisites
- None curated yet.
Module targets
module-01-c-programming-fundamentals
AI companion modes
- Explain simply
- Socratic tutor
- Quiz me
- Challenge my understanding
- Diagnose my confusion
- Generate extra practice
- Revision mode
- Connect forward / backward
Source-of-truth note
This unit is anchored to The C Programming Language and the source chapter "A 10 External Declarations". Use external resources only to clarify, extend, or modernize details without replacing the chapter's conceptual spine.
External enrichment
No chapter-specific enrichment resources are curated yet. Add them in the unit manifest when a source clearly improves learning.
Source provenance
- Primary source:
The C Programming Language - Source chapter: A 10 External Declarations
- Raw source file:
073-a-10-external-declarations.md
Merged source
A 10 External Declarations
A.10 External Declarations
The unit of input provided to the C compiler is called a translation unit; it consists of a sequence of external declarations, which are either declarations or function definitions.
translation-unit:
external-declaration translation-unit external-declaration external-declaration:
function-definition
declaration
The scope of external declarations persists to the end of the translation unit in which they are declared, just as the effect of declarations within the blocks persists to the end of the block.
The syntax of external declarations is the same as that of all declarations, except that only at this level may the code for functions be given.
A.10.1 Function Definitions
Function definitions have the form function-definition:
declaration-specifiersopt declarator declaration-listopt compound-statement
The only storage-class specifiers allowed among the declaration specifiers are extern or static; see Par.A.11.2 for the distinction between them.
A function may return an arithmetic type, a structure, a union, a pointer, or void, but not a function or an array. The declarator in a function declaration must specify explicitly that the declared identifier has function type; that is, it must contain one of the forms (see Par.A.8.6.3).
direct-declarator( parameter-type-list) direct-declarator( identifier-listopt ) where the direct-declarator is an identifier or a parenthesized identifier. In particular, it must not achieve function type by means of atypedef.
In the first form, the definition is a new-style function, and its parameters, together with their types, are declared in its parameter type list; the declaration-list following the function's declarator must be absent. Unless the parameter type list consists solely ofvoid, showing that the function takes no parameters, each declarator in the parameter type list must contain an identifier. If the parameter type list ends with ``, ...'' then the function may be called with more arguments than parameters; theva_argmacro mechanism defined in the standard header
<stdarg.h> and described in Appendix B must be used to refer to the extra arguments.
Variadic functions must have at least one named parameter.
In the second form, the definition is old-style: the identifier list names the parameters, while the declaration list attributes types to them. If no declaration is given for a parameter, its type is taken to be int. The declaration list must declare only parameters named in the list, initialization is not permitted, and the only storage-class specifier possible isregister.
In both styles of function definition, the parameters are understood to be declared just after the beginning of the compound statement constituting the function's body, and thus the same identifiers must not be redeclared there (although they may, like other identifiers, be redeclared in inner blocks). If a parameter is declared to have type array of type,'' the declaration is adjusted to read pointer to type;'' similarly, if a parameter is declared to have type function returningtype,'' the declaration is adjusted to read pointer to function returningtype.'' During the call to a function, the arguments are converted as necessary and assigned to the parameters; see Par.A.7.3.2.
New-style function definitions are new with the ANSI standard. There is also a small change in the details of promotion; the first edition specified that the declarations of float parameters were adjusted to read double. The difference becomes noticable when a pointer to a parameter is generated within a function.
A complete example of a new-style function definition is
int max(int a, int b, int c)
{
int m;
m = (a > b) ? a : b;
return (m > c) ? m : c;
}
Hereintis the declaration specifier;max(int a, int b, int c)is the function's declarator, and { ... } is the block giving the code for the function. The corresponding old-style
definition would be
int max(a, b, c)
int a, b, c;
{
/* ... */
}
where nowint max(a, b, c)is the declarator, andint a, b, c;is the declaration list for the parameters.
A.10.2 External Declarations
External declarations specify the characteristics of objects, functions and other identifiers. The term ``external'' refers to their location outside functions, and is not directly connected with the externkeyword; the storage class for an externally-declared object may be left empty, or it may be specified asexternorstatic.
Several external declarations for the same identifier may exist within the same translation unit if they agree in type and linkage, and if there is at most one definition for the identifier.
Two declarations for an object or function are deemed to agree in type under the rule discussed in Par.A.8.10. In addition, if the declarations differ because one type is an incomplete structure, union, or enumeration type (Par.A.8.3) and the other is the corresponding completed type with the same tag, the types are taken to agree. Moreover, if one type is an incomplete array type (Par.A.8.6.2) and the other is a completed array type, the types, if otherwise identical, are also taken to agree. Finally, if one type specifies an old-style function, and the other an otherwise identical new-style function, with parameter declarations, the types are taken to agree.
If the first external declarator for a function or object includes the static specifier, the identifier has internal linkage; otherwise it has external linkage. Linkage is discussed in
Par.11.2.
An external declaration for an object is a definition if it has an initializer. An external object declaration that does not have an initializer, and does not contain the externspecifier, is a tentative definition. If a definition for an object appears in a translation unit, any tentative definitions are treated merely as redundant declarations. If no definition for the object appears in the translation unit, all its tentative definitions become a single definition with initializer 0.
Each object must have exactly one definition. For objects with internal linkage, this rule applies separately to each translation unit, because internally-linked objects are unique to a translation unit. For objects with external linkage, it applies to the entire program.
Although the one-definition rule is formulated somewhat differently in the first edition of this book, it is in effect identical to the one stated here. Some implementations relax it by generalizing the notion of tentative definition. In the alternate formulation, which is usual in UNIX systems and recognized as a common extension by the Standard, all the tentative definitions for an externally linked object, throughout all the translation units of the program, are considered together instead of in each translation unit separately. If a definition occurs somewhere in the program, then the tentative definitions become merely declarations, but if no definition appears, then all its tentative definitions become a definition with initializer 0.