6.9.0 General
translation-unit:
external-declaration
translation-unit external-declaration
external-declaration:
function-definition
declaration
A translation unit consists of a sequence of external declarations, each of which is a declaration or a function definition.
An external definition is an external declaration that is also a definition. An entity with external linkage that is used by a program shall have exactly one external definition in the whole program.
Constraints.
The storage-class specifier of an external declaration shall be static, extern, typedef, or absent.
ISO C99 mapping: 6.9.
6.9.1 Function Definitions
function-definition:
declaration-specifiers declarator compound-statement
Constraints.
The declarator shall be a function declarator with a complete parameter type list, under clause 6.7.5.3.
Every parameter shall have a name.
The return type shall not be an array type and shall not be a function type.
The storage-class specifier shall be static or absent. extern on a function definition is a constraint violation, for the same reason it is one on an object definition: extern declares, and a definition defines.
A function shall not be defined more than once in one translation unit.
Old-style parameter declaration lists between the declarator and the body are a constraint violation. See clause 6.7.5.3.
Semantics.
int add(int a, int b)
{
return a + b;
}
Parameters are objects with automatic storage duration, initialized on entry with the converted argument values.
On entry, storage is reserved for the function's automatic objects. Each begins its lifetime with a valid value when its declaration is reached, under clause 6.7.9.2.
The function terminates by executing a return, by reaching the closing brace of a void function, by reaching the closing brace of main, or by a defined trap. See clause 6.8.6.4.
Recursion. Every function may be called recursively, directly or indirectly.
ISO C99 mapping: 6.9.1.
6.9.2 External Object Definitions
At file scope, a declaration with no extern is a definition.
int counter; /* definition; one zero-initialized object */
int total = 10; /* definition with an explicit initializer */
extern int counter; /* declaration of an object defined elsewhere */
static int local_count; /* definition with internal linkage */
Tentative definitions do not exist.
A translation unit shall not contain more than one definition of the same object. Repeating:
int counter;
int counter; /* constraint violation */
is an error rather than a pair of tentative definitions to be reconciled later.
A definition may be preceded and followed by any number of compatible extern declarations, which declare it without defining it again.
Difference: ISO C99 gives file-scope declarations without an initializer a special tentative status, permits any number of them, and merges them into a single definition at the end of the translation unit. The category is removed here. The distinction becomes simply:
definition
external declaration
See syntax.md section 16 and behavior.md section 47.
Initialization. Every object with static storage duration is initialized before program startup, from its initializer if it has one and from clause 6.7.9.2 otherwise.
ISO C99 mapping: 6.9.2.
6.9.3 Header Organization
A header is a source file intended to be included by more than one translation unit. Headers are not a separate language construct, and this clause states practice rather than syntax.
A header should contain declarations, type definitions, and static inline function definitions. A header should not contain an object definition, because including it in two translation units then produces two definitions of the same external entity.
/* buffer.h */
#pragma once
#include <stddef.h>
#include <stdint.h>
struct Buffer
{
uint8_t *data;
size_t length;
size_t capacity;
};
extern int buffer_reserve(struct Buffer *buffer, size_t capacity);
static inline size_t buffer_available(const struct Buffer *buffer)
{
return buffer->capacity - buffer->length;
}
A header reached by #include shall be protected against repeated inclusion, by #pragma once as above or by an include guard. A header reached only by #import needs no protection, since importing is idempotent under clause 6.10.11. Both mechanisms are required of every implementation, and clause 6.10.2.1 describes when to prefer each. A header shared with ISO C source should use an include guard, because #pragma once is guaranteed only within this edition.
The requirement is not a style preference. The header above defines a structure and a static inline function, and each may be defined only once in a translation unit under clause 6.7.2.4 and clause 6.9.1. Reaching it twice through an indirect path without protection is therefore a constraint violation rather than a harmless repetition. Clause 6.10.2.3 states which constructs survive a second inclusion and which do not.
An implementation may process a repeated inclusion structurally rather than textually, and shall produce the same result either way. See clause 6.10.2.
ISO C99 mapping: new. ISO C99 describes headers only through the library and the #include directive.
6.9.4 The Whole Program
A program is formed by combining translation units and library components.
One definition.
For each entity with external linkage that a program uses, the program shall contain exactly one external definition. Entities with external linkage are the same entity when their linkage names are the same, under clause 6.2.2.3, so two entities in different namespaces are distinct and each may be defined. Using an entity means calling it, taking its address, or accessing it in a way that requires the definition to exist.
An entity with external linkage that is declared but never used need not be defined.
Consistency.
Every declaration of an entity with external linkage, in every translation unit of the program, shall declare a compatible type under clause 6.2.7.
An implementation shall diagnose a type mismatch it can detect, which includes every mismatch visible within one translation unit and, where the implementation performs whole-program analysis or records type information in object files, mismatches across translation units. An undetected mismatch is unsafe memory behavior.
Duplicate definitions.
A second definition of the same externally linked entity is invalid, unless a platform linkage mechanism explicitly provides for it, such as a documented weak-symbol facility. An implementation that provides such a mechanism shall document its resolution rule.
ISO C99 mapping: 6.9, paragraph 5.
6.9.5 Redeclaration
An identifier may be declared more than once in the same scope when every declaration is compatible.
For an object with external or internal linkage:
- the types shall be compatible,
- the composite type of all declarations is the type of the entity,
- at most one declaration shall be a definition,
- at most one declaration shall have an initializer,
- the linkage shall be consistent, under clause 6.2.2.2.
For a function:
- the return types and parameter type lists shall be compatible,
- at most one declaration shall be a definition,
- a later declaration shall not add or remove
static, - a later declaration shall not add
inlineto a function already declared without it, and shall not remove it.
An implementation shall diagnose an incompatible redeclaration and shall name both declarations in the diagnostic.
ISO C99 mapping: 6.7, paragraph 4, and 6.2.7.
6.9.6 Namespaces
6.9.6.1 General
A namespace is a named region of declarations. Its members are reached by qualification, and its members with external linkage have linkage names distinguished from those of every other namespace.
A namespace assigns names. It does not control visibility, does not describe dependency, does not affect layout or representation, and does not introduce any runtime concept. See clause 1.5 for the test this facility had to pass and syntax.md section 5.1 for the reasoning.
A program is placed into a namespace in one of two ways:
The two are equivalent in effect. They differ in how much source they govern.
6.9.6.2 The global namespace
Declarations not contained by any namespace are members of the global namespace.
The global namespace has no name. Its members are named with a leading ::, or without qualification wherever lookup reaches them under clause 6.5.1.3.
Every entity of the standard library is a member of the global namespace, and so is every entity declared by an ISO C translation unit. This is what makes the mechanism additive: a program that declares no namespace is entirely in the global namespace and behaves exactly as it did.
6.9.6.3 Membership
Every declaration is a member of exactly one namespace, determined by where it appears.
Membership is a property of the name. Two entities in different namespaces are as unrelated as two entities with different names, and no relationship exists between a namespace and the entities of any other.
Membership does not affect:
- the type of an entity,
- its storage duration, lifetime, alignment, or representation,
- how it is called or what its parameters are,
- whether it is
const,volatile, orrestrict, - the layout of any structure or union.
6.9.6.4 Linkage names
The linkage name of an entity with external linkage declared inside a namespace is formed by writing each enclosing namespace name from outermost to innermost, each followed by two underscore characters, then the identifier.
net::open net__open
net::tcp::open net__tcp__open
open open
The mapping is fixed by this specification. It is not implementation-defined, and an implementation shall not use another encoding.
Two properties follow, and both are intended.
It is injective. Clause 6.4.2.0 forbids two consecutive underscores in a namespace name and in an exported identifier inside a namespace, so no two distinct qualified names produce the same linkage name.
It is an ordinary C identifier. A linkage name contains only characters an identifier may contain, so it can be declared, called, and linked by an ISO C translation unit with no shim, no wrapper, and no attribute.
An entity with internal linkage or with no linkage has no linkage name. static inside a namespace exports nothing.
6.9.6.5 Interoperation with C
Calling an Ocean Edition I entity from C.
A C translation unit declares the linkage name:
/* Ocean Edition I */
namespace net
{
int open(const char *host);
}
/* ISO C */
extern int net__open(const char *host);
The declaration is ordinary C, the call is an ordinary call, and the two translation units link.
Calling a C entity from Ocean Edition I.
A C entity is a member of the global namespace. It is reached by unqualified lookup from anywhere, or by :: where a nearer declaration would otherwise be found:
namespace net
{
int open(const char *host)
{
return socket(AF_INET, SOCK_STREAM, 0);
}
}
Giving an entity an unqualified external name.
An entity that shall be exported under a plain identifier is declared in the global namespace. No further mechanism is provided, and none is needed:
int net_open(const char *host); /* exported as net_open */
This edition adds no extern "C" equivalent, because placing a declaration outside a namespace already expresses the requirement using syntax the language already has.
6.9.6.6 Declarations and definitions of members
The ordinary rules of clause 6.9 apply to a namespace member without change. Membership decides the name, and nothing else.
An extern declaration inside a namespace declares a member defined elsewhere in the same namespace:
/* counters.h */
#namespace "net"
extern int open_count;
/* counters.c */
#namespace "net"
int open_count;
Both refer to the entity whose linkage name is net__open_count. An extern declaration does not define, under clause 6.2.2.4, and it does not change the namespace of what it declares.
A definition and its declarations shall be in the same namespace. An extern declaration in one namespace does not reach an entity in another, since the two have different linkage names, and no diagnostic is possible at the point of declaration: the program simply refers to an entity nothing defines, and the link fails.
Redeclaration follows clause 6.9.5, applied within a namespace. The whole-program rules of clause 6.9.4 apply to linkage names, so an entity is defined once per linkage name rather than once per identifier.
6.9.6.7 Constraints
main shall be a member of the global namespace. A hosted program has one entry function, the execution environment finds it by an unqualified name, and a namespaced main would not be that function.
A namespace name shall not be main, and shall not be an identifier reserved under clause 6.4.2.1.
A declaration with external linkage in a namespace shall not have a linkage name equal to the linkage name of any other entity in the program. Where an implementation can detect a collision it shall diagnose it.
Note on collisions with C. The linkage name of net::open is net__open, and a C library is free to export a function of that name. The restriction of clause 6.4.2.0 makes the mapping injective within this edition, and it cannot constrain code written in another language. An implementation shall diagnose a collision it can see, and a program linking against a library that exports names containing consecutive underscores should choose namespace names accordingly. The residual risk is the same one the prefix convention already carries, and it is smaller, because the mangling is systematic rather than ad hoc.
6.9.6.8 What namespaces are not
The following are stated so that no reader infers a facility this edition does not provide.
- There is no mechanism to bring a namespace member into scope unqualified. No
using, no alias, nofrom. - There is no re-export. A namespace does not acquire the members of any other.
- There is no visibility control beyond
static. A member is exported or it is not. - There is no interface file, no module boundary, and no dependency description. Dependency remains the business of the header.
- A namespace is not a scope in the sense of clause 6.2.1, is not an object, and cannot be named as a value or as a type.
- Namespace membership is not part of a type. Two functions differing only in namespace do not overload; they are simply two functions with different names.
ISO C99 mapping: new. Added under clause 1.5.
6.9.7 The Entry Point
A hosted program has exactly one externally visible entry function, main, as clause 5.1.2.2 defines.
main shall not be declared static or inline, shall be a member of the global namespace under clause 6.9.6.7, and the program shall not call it.
A freestanding program's entry point is implementation-defined, and the implementation shall document its name and its signature.
ISO C99 mapping: 5.1.2.2.
6.9.8 Example Translation Unit
The following is an ordinary Ocean Edition I source file. Nothing in it announces that a different language is being used.
#include <stddef.h>
#include <stdint.h>
#include "buffer.h"
static inline size_t min_size(size_t a, size_t b)
{
return a < b ? a : b;
}
static int buffer_copy(
struct Buffer *dst,
const struct Buffer *src
)
{
if (dst == null || src == null)
{
return -1;
}
size_t count = min_size(dst->capacity, src->length);
copy_bytes(
&dst->data[0],
&src->data[0],
count
);
dst->length = count;
return 0;
}
int main(void)
{
struct Buffer buffer = {
.data = null,
.length = 0,
.capacity = 0,
};
run(&buffer);
return 0;
}
The differences from traditional C are visible only where they matter: &dst->data[0] says that an element pointer was wanted, min_size is static inline rather than a macro, and buffer would begin zero-filled even without its initializer. See syntax.md section 61.