Chapter 18: Declarations
Copyright 2008 W. W. Norton & Company.
All rights reserved.
1
Chapter 18
Declarations
Chapter 18: Declarations
Declaration Syntax
 Declarations furnish information to the compiler about 
the meaning of identifiers.
 Examples:
i nt   i ;
f l oat   f ( f l oat ) ;
 General form of a declaration:
declaration-specifiers   declarators ;
 Declaration specifiers describe the properties of the 
variables or functions being declared.
 Declarators give their names and may provide 
additional information about their properties.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
2
Chapter 18: Declarations
Declaration Syntax
 Declaration specifiers fall into three categories:
 Storage classes
 Type qualifiers
 Type specifiers
 C99 has a fourth category, function specifiers,
which are used only in function declarations.
 This category has one member, the keyword i nl i ne.
 Type qualifiers and type specifiers should follow 
the storage class, but there are no other restrictions 
on their order.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
3
Chapter 18: Declarations
Declaration Syntax
 There are four storage classes: aut o, st at i c, 
ext er n, and r egi st er .
 At most one storage class may appear in a 
declaration; if present, it should come first.
 In C89, there are only two type qualifiers: const
and vol at i l e.
 C99 has a third type qualifier, r est r i ct .
 A declaration may contain zero or more type 
qualifiers.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
4
Chapter 18: Declarations
Declaration Syntax
 The keywords voi d, char , shor t , i nt , l ong, 
f l oat , doubl e, si gned, and unsi gned are all 
type specifiers.
 The order in which they are combined doesnt matter.
 i nt unsi gned l ong is the same as l ong unsi gned
i nt .
 Type specifiers also include specifications of 
structures, unions, and enumerations.
 Examples: st r uct poi nt { i nt x, y; },
st r uct { i nt x, y; }, st r uct poi nt .
 t ypedef names are also type specifiers.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
5
Chapter 18: Declarations
Declaration Syntax
 Declarators include:
 Identifiers (names of simple variables)
 Identifiers followed by [ ] (array names)
 Identifiers preceded by * (pointer names)
 Identifiers followed by ( ) (function names)
 Declarators are separated by commas.
 A declarator that represents a variable may be 
followed by an initializer.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
6
Chapter 18: Declarations
Declaration Syntax
 A declaration with a storage class and three declarators:
 A declaration with a type qualifier and initializer but no 
storage class:
Copyright 2008 W. W. Norton & Company.
All rights reserved.
7
Chapter 18: Declarations
Declaration Syntax
 A declaration with a storage class, a type qualifier, and 
three type specifiers:
 Function declarations may have a storage class, type 
qualifiers, and type specifiers:
Copyright 2008 W. W. Norton & Company.
All rights reserved.
8
Chapter 18: Declarations
Storage Classes
 Storage classes can be specified for variables 
andto a lesser extentfunctions and 
parameters.
 Recall that the term block refers to the body of a 
function (the part in braces) or a compound 
statement, possibly containing declarations.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
9
Chapter 18: Declarations
Properties of Variables
 Every variable in a C program has three 
properties:
 Storage duration
 Scope
 Linkage
Copyright 2008 W. W. Norton & Company.
All rights reserved.
10
Chapter 18: Declarations
Properties of Variables
 The storage duration of a variable determines 
when memory is set aside for the variable and 
when that memory is released.
 Automatic storage duration: Memory for variable is 
allocated when the surrounding block is executed and 
deallocated when the block terminates.
 Static storage duration: Variable stays at the same 
storage location as long as the program is running, 
allowing it to retain its value indefinitely.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
11
Chapter 18: Declarations
Properties of Variables
 The scope of a variable is the portion of the 
program text in which the variable can be 
referenced.
 Block scope: Variable is visible from its point of 
declaration to the end of the enclosing block.
 File scope: Variable is visible from its point of 
declaration to the end of the enclosing file.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
12
Chapter 18: Declarations
Properties of Variables
 The linkage of a variable determines the extent to 
which it can be shared.
 External linkage: Variable may be shared by several 
(perhaps all) files in a program.
 Internal linkage: Variable is restricted to a single file 
but may be shared by the functions in that file.
 No linkage: Variable belongs to a single function and 
cant be shared at all.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
13
Chapter 18: Declarations
Properties of Variables
 The default storage duration, scope, and linkage of 
a variable depend on where its declared:
 Variables declared inside a block (including a function 
body) have automatic storage duration, block scope, 
and no linkage.
 Variables declared outside any block, at the outermost 
level of a program, have static storage duration, file
scope, and external linkage.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
14
Chapter 18: Declarations
Properties of Variables
 Example:
 We can alter these properties by specifying an explicit 
storage class: aut o, st at i c, ext er n, or r egi st er .
Copyright 2008 W. W. Norton & Company.
All rights reserved.
15
Chapter 18: Declarations
The auto Storage Class
 The aut o storage class is legal only for variables 
that belong to a block.
 An aut o variable has automatic storage duration, 
block scope, and no linkage.
 The aut o storage class is almost never specified 
explicitly.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
16
Chapter 18: Declarations
The static Storage Class
 The st at i c storage class can be used with all 
variables, regardless of where theyre declared.
 When used outside a block, st at i c specifies that a 
variable has internal linkage.
 When used inside a block, st at i c changes the 
variables storage duration from automatic to static.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
17
Chapter 18: Declarations
The static Storage Class
 Example:
Copyright 2008 W. W. Norton & Company.
All rights reserved.
18
Chapter 18: Declarations
The static Storage Class
 When used outside a block, st at i c hides a variable 
within a file:
st at i c  i nt   i ; / * no access t o i i n ot her f i l es */
voi d  f 1( voi d)
{
/ *  has  access  t o  i   */
}
voi d  f 2( voi d)
{
/ *  has  access  t o  i   */
}
 This use of st at i c is helpful for implementing 
information hiding.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
19
Chapter 18: Declarations
The static Storage Class
 A st at i c variable declared within a block 
resides at the same storage location throughout 
program execution.
 A st at i c variable retains its value indefinitely.
 Properties of st at i c variables:
 A st at i c variable is initialized only once, prior to 
program execution.
 A st at i c variable declared inside a function is shared 
by all calls of the function, including recursive calls.
 A function may return a pointer to a st at i c variable.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
20
Chapter 18: Declarations
The static Storage Class
 Declaring a local variable to be st at i c allows a 
function to retain information between calls.
 More often, well use st at i c for reasons of 
efficiency:
char   di gi t _t o_hex_char ( i nt   di gi t )
{
st at i c  const   char   hex_char s[ 16]   =
" 0123456789ABCDEF" ;
r et ur n  hex_char s[ di gi t ] ;
}
 Declaring hex_char s to be st at i c saves time, 
because st at i c variables are initialized only once.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
21
Chapter 18: Declarations
The extern Storage Class
 The ext er n storage class enables several source 
files to share the same variable.
 A variable declaration that uses ext er n doesnt 
cause memory to be allocated for the variable:
ext er n  i nt   i ;
In C terminology, this is not a definition of i .
 An ext er n declaration tells the compiler that we 
need access to a variable thats defined elsewhere.
 A variable can have many declarations in a 
program but should have only one definition.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
22
Chapter 18: Declarations
The extern Storage Class
 Theres one exception to the rule that an ext er n
declaration of a variable isnt a definition.
 An ext er n declaration that initializes a variable 
serves as a definition of the variable.
 For example, the declaration
ext er n  i nt   i   =  0;
is effectively the same as
i nt   i   =  0;
 This rule prevents multiple ext er n declarations 
from initializing a variable in different ways.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
23
Chapter 18: Declarations
The extern Storage Class
 A variable in an ext er n declaration always has 
static storage duration.
 If the declaration is inside a block, the variable has 
block scope; otherwise, it has file scope:
Copyright 2008 W. W. Norton & Company.
All rights reserved.
24
Chapter 18: Declarations
The extern Storage Class
 Determining the linkage of an ext er n variable is 
a bit harder.
 If the variable was declared st at i c earlier in the file 
(outside of any function definition), then it has internal 
linkage.
 Otherwise (the normal case), the variable has external 
linkage.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
25
Chapter 18: Declarations
The register Storage Class
 Using the r egi st er storage class in the 
declaration of a variable asks the compiler to store 
the variable in a register.
 A register is a high-speed storage area located in a 
computers CPU.
 Specifying the storage class of a variable to be 
r egi st er is a request, not a command.
 The compiler is free to store a r egi st er
variable in memory if it chooses.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
26
Chapter 18: Declarations
The register Storage Class
 The r egi st er storage class is legal only for 
variables declared in a block.
 A r egi st er variable has the same storage 
duration, scope, and linkage as an aut o variable.
 Since registers dont have addresses, its illegal to 
use the &operator to take the address of a 
r egi st er variable.
 This restriction applies even if the compiler has 
elected to store the variable in memory.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
27
Chapter 18: Declarations
The register Storage Class
 r egi st er is best used for variables that are 
accessed and/or updated frequently.
 The loop control variable in a f or statement is a 
good candidate for r egi st er treatment:
i nt   sum_ar r ay( i nt   a[ ] ,   i nt   n)
{
r egi st er   i nt   i ;
i nt   sum=  0;
f or   ( i   =  0;   i   <  n;   i ++)
sum+=  a[ i ] ;
r et ur n  sum;
}
Copyright 2008 W. W. Norton & Company.
All rights reserved.
28
Chapter 18: Declarations
The register Storage Class
 r egi st er isnt as popular as it once was.
 Many of todays compilers can determine 
automatically which variables would benefit from 
being kept in registers.
 Still, using r egi st er provides useful 
information that can help the compiler optimize 
the performance of a program.
 In particular, the compiler knows that a 
r egi st er variable cant have its address taken, 
and therefore cant be modified through a pointer.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
29
Chapter 18: Declarations
The Storage Class of a Function
 Function declarations (and definitions) may 
include a storage class.
 The only options are ext er n and st at i c:
 ext er n specifies that the function has external 
linkage, allowing it to be called from other files.
 st at i c indicates internal linkage, limiting use of the 
functions name to the file in which its defined.
 If no storage class is specified, the function is 
assumed to have external linkage.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
30
Chapter 18: Declarations
The Storage Class of a Function
 Examples:
ext er n  i nt   f ( i nt   i ) ;
st at i c  i nt   g( i nt   i ) ;
i nt   h( i nt   i ) ;
 Using ext er n is unnecessary, but st at i c has 
benefits:
 Easier maintenance. A st at i c function isnt visible 
outside the file in which its definition appears, so future 
modifications to the function wont affect other files.
 Reduced name space pollution. Names of st at i c
functions dont conflict with names used in other files.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
31
Chapter 18: Declarations
The Storage Class of a Function
 Function parameters have the same properties as 
aut o variables: automatic storage duration, block 
scope, and no linkage.
 The only storage class that can be specified for 
parameters is r egi st er .
Copyright 2008 W. W. Norton & Company.
All rights reserved.
32
Chapter 18: Declarations
Summary
 A program fragment that shows all possible ways to 
includeor omitstorage classes in declarations of 
variables and parameters:
i nt   a;
ext er n  i nt   b;
st at i c  i nt   c;
voi d  f ( i nt   d,   r egi st er   i nt   e)
{
aut o  i nt   g;
i nt   h;
st at i c  i nt   i ;
ext er n  i nt   j ;
r egi st er   i nt   k;
}
Copyright 2008 W. W. Norton & Company.
All rights reserved.
33
Chapter 18: Declarations
Summary
Name Storage Duration Scope Linkage
a static file external
b static file 
c static file internal
d automatic block none
e automatic block none
g automatic block none
h automatic block none
i static block none
j static block 
k automatic block none
In most cases, b and j will be defined in another file and will 
have external linkage.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
34
Chapter 18: Declarations
Summary
 Of the four storage classes, the most important are 
st at i c and ext er n.
 aut o has no effect, and modern compilers have 
made r egi st er less important.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
35
Chapter 18: Declarations
Type Qualifiers
 There are two type qualifiers: const and 
vol at i l e.
 C99 has a third type qualifier, r est r i ct , which is 
used only with pointers.
 vol at i l e is discussed in Chapter 20.
 const is used to declare read-only objects.
 Examples:
const   i nt   n  =  10;
const   i nt   t ax_br acket s[ ]   =
{750,   2250,   3750,   5250,   7000};
Copyright 2008 W. W. Norton & Company.
All rights reserved.
36
Chapter 18: Declarations
Type Qualifiers
 Advantages of declaring an object to be const :
 Serves as a form of documentation.
 Allows the compiler to check that the value of the 
object isnt changed.
 Alerts the compiler that the object can be stored in 
ROM (read-only memory).
Copyright 2008 W. W. Norton & Company.
All rights reserved.
37
Chapter 18: Declarations
Type Qualifiers
 It might appear that const serves the same role 
as the #def i ne directive, but there are 
significant differences between the two features.
 #def i ne can be used to create a name for a 
numerical, character, or string constant, but 
const can create read-only objects of any type.
 const objects are subject to the same scope rules 
as variables; constants created using #def i ne
arent.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
38
Chapter 18: Declarations
Type Qualifiers
 The value of a const object, unlike the value of a 
macro, can be viewed in a debugger.
 Unlike macros, const objects cant be used in 
constant expressions:
const   i nt   n  =  10;
i nt   a[ n] ;                       / ***  WRONG  ***/
 Its legal to apply the address operator (&) to a 
const object, since it has an address; a macro 
doesnt have an address.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
39
Chapter 18: Declarations
Type Qualifiers
 There are no absolute rules that dictate when to 
use #def i ne and when to use const .
 #def i ne is good for constants that represent 
numbers or characters.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
40
Chapter 18: Declarations
Declarators
 In the simplest case, a declarator is just an 
identifier:
i nt   i ;
 Declarators may also contain the symbols *, [ ] , 
and ( ) .
 A declarator that begins with * represents a 
pointer:
i nt   *p;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
41
Chapter 18: Declarations
Declarators
 A declarator that ends with [ ] represents an array:
i nt   a[ 10] ;
 The brackets may be left empty if the array is a 
parameter, if it has an initializer, or if its storage 
class is ext er n:
ext er n  i nt   a[ ] ;
 In the case of a multidimensional array, only the 
first set of brackets can be empty.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
42
Chapter 18: Declarations
Declarators
 C99 provides two additional options for what goes 
between the brackets in the declaration of an array 
parameter:
 The keyword st at i c, followed by an expression that 
specifies the arrays minimum length.
 The * symbol, which can be used in a function 
prototype to indicate a variable-length array argument.
 Chapter 9 discusses both features.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
43
Chapter 18: Declarations
Declarators
 A declarator that ends with ( ) represents a 
function:
i nt   abs( i nt   i ) ;
voi d  swap( i nt   *a,   i nt   *b) ;
i nt   f i nd_l ar gest ( i nt   a[ ] ,   i nt   n) ;
 C allows parameter names to be omitted in a 
function declaration:
i nt   abs( i nt ) ;
voi d  swap( i nt   *,   i nt   *) ;
i nt   f i nd_l ar gest ( i nt   [ ] ,   i nt ) ;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
44
Chapter 18: Declarations
Declarators
 The parentheses can even be left empty:
i nt   abs( ) ;
voi d  swap( ) ;
i nt   f i nd_l ar gest ( ) ;
This provides no information about the arguments.
 Putting the word voi d between the parentheses is 
different: it indicates that there are no arguments.
 The empty-parentheses style doesnt let the 
compiler check whether function calls have the 
right arguments. 
Copyright 2008 W. W. Norton & Company.
All rights reserved.
45
Chapter 18: Declarations
Declarators
 Declarators in actual programs often combine the 
*, [ ] , and ( ) notations.
 An array of 10 pointers to integers:
i nt   *ap[ 10] ;
 A function that has a f l oat argument and returns 
a pointer to a f l oat :
f l oat   *f p( f l oat ) ;
 A pointer to a function with an i nt argument and 
a voi d return type:
voi d  ( *pf ) ( i nt ) ;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
46
Chapter 18: Declarations
Deciphering Complex Declarations
 But what about declarators like the one in the 
following declaration?
i nt   *( *x[ 10] ) ( voi d) ;
 Its not obvious whether x is a pointer, an array, or 
a function.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
47
Chapter 18: Declarations
Deciphering Complex Declarations
 Rules for understanding declarations:
 Always read declarators from the inside out. Locate 
the identifier thats being declared, and start 
deciphering the declaration from there.
 When theres a choice, always favor [] and () over 
*. Parentheses can be used to override the normal 
priority of [ ] and ( ) over *.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
48
Chapter 18: Declarations
Deciphering Complex Declarations
 Example 1:
i nt   *ap[ 10] ;
ap is an array of pointers.
 Example 2:
f l oat   *f p( f l oat ) ;
f p is a function that returns a pointer.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
49
Chapter 18: Declarations
Deciphering Complex Declarations
 Example 3:
voi d  ( *pf ) ( i nt ) ;
 Since *pf is enclosed in parentheses, pf must be 
a pointer.
 But ( *pf ) is followed by ( i nt ) , so pf must 
point to a function with an i nt argument.
 The word voi d represents the return type of this 
function.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
50
Chapter 18: Declarations
Deciphering Complex Declarations
 Understanding a complex declarator often 
involves zigzagging from one side of the identifier 
to the other:
Copyright 2008 W. W. Norton & Company.
All rights reserved.
51
Chapter 18: Declarations
Deciphering Complex Declarations
 A second example of zigzagging:
Copyright 2008 W. W. Norton & Company.
All rights reserved.
52
Chapter 18: Declarations
Deciphering Complex Declarations
 Certain things cant be declared in C.
 Functions cant return arrays:
i nt   f ( i nt ) [ ] ;             / ***  WRONG  ***/
 Functions cant return functions:
i nt   g( i nt ) ( i nt ) ;       / ***  WRONG  ***/
 Arrays of functions arent possible, either:
i nt   a[ 10] ( i nt ) ;         / ***  WRONG  ***/
 In each case, pointers can be used to get the desired 
effect.
 For example, a function cant return an array, but it 
can return a pointer to an array.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
53
Chapter 18: Declarations
Using Type Definitions to Simplify Declarations
 Some programmers use type definitions to help 
simplify complex declarations.
 Suppose that x is declared as follows:
i nt   *( *x[ 10] ) ( voi d) ;
 The following type definitions make xs type 
easier to understand:
t ypedef   i nt   *Fcn( voi d) ;
t ypedef   Fcn  *Fcn_pt r ;
t ypedef   Fcn_pt r   Fcn_pt r _ar r ay[ 10] ;
Fcn_pt r _ar r ay  x;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
54
Chapter 18: Declarations
Initializers
 For convenience, C allows us to specify initial 
values for variables as were declaring them.
 To initialize a variable, we write the =symbol 
after its declarator, then follow that with an 
initializer.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
55
Chapter 18: Declarations
Initializers
 The initializer for a simple variable is an 
expression of the same type as the variable:
i nt   i   =  5  /   2;       / *  i   i s  i ni t i al l y  2  */
 If the types dont match, C converts the initializer 
using the same rules as for assignment:
i nt   j   =  5. 5;           / *  conver t ed  t o  5  */
 The initializer for a pointer variable must be an 
expression of the same type or of type voi d *:
i nt   *p  =  &i ;
Copyright 2008 W. W. Norton & Company.
All rights reserved.
56
Chapter 18: Declarations
Initializers
 The initializer for an array, structure, or union is 
usually a series of values enclosed in braces:
i nt   a[ 5]   =  {1,   2,   3,   4,   5};
 In C99, brace-enclosed initializers can have other 
forms, thanks to designated initializers.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
57
Chapter 18: Declarations
Initializers
 An initializer for a variable with static storage 
duration must be constant:
#def i ne  FI RST  1
#def i ne  LAST  100
st at i c  i nt   i   =  LAST  - FI RST  +  1;
 If LAST and FI RST had been variables, the 
initializer would be illegal.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
58
Chapter 18: Declarations
Initializers
 If a variable has automatic storage duration, its 
initializer need not be constant:
i nt   f ( i nt   n)
{
i nt   l ast   =  n  - 1;
}
Copyright 2008 W. W. Norton & Company.
All rights reserved.
59
Chapter 18: Declarations
Initializers
 A brace-enclosed initializer for an array, structure, 
or union must contain only constant expressions:
#def i ne  N  2
i nt   power s[ 5]   =
{1, N, N * N, N * N * N, N * N * N * N};
 If Nwere a variable, the initializer would be 
illegal.
 In C99, this restriction applies only if the variable 
has static storage duration.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
60
Chapter 18: Declarations
Initializers
 The initializer for an automatic structure or union 
can be another structure or union:
voi d  g( st r uct   par t   par t 1)
{
st r uct   par t   par t 2  =  par t 1;
}
 The initializer doesnt have to be a variable or 
parameter name, although it does need to be an 
expression of the proper type.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
61
Chapter 18: Declarations
Uninitialized Variables
 The initial value of a variable depends on its 
storage duration:
 Variables with automatic storage duration have no 
default initial value.
 Variables with static storage duration have the value 
zero by default.
 A static variable is correctly initialized based on 
its type, not simply set to zero bits.
 Its better to provide initializers for static variables 
rather than rely on the fact that theyre guaranteed 
to be zero.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
62
Chapter 18: Declarations
Inline Functions (C99)
 C99 function declarations may contain the 
keyword i nl i ne.
 i nl i ne is related to the concept of the 
overhead of a function callthe work required 
to call a function and later return from it.
 Although the overhead of a function call slows the 
program by only a tiny amount, it may add up in 
certain situations.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
63
Chapter 18: Declarations
Inline Functions (C99)
 In C89, the only way to avoid the overhead of a 
function call is to use a parameterized macro.
 C99 offers a better solution to this problem: create 
an inline function.
 The word inline suggests that the compiler 
replaces each call of the function by the machine 
instructions for the function.
 This technique may cause a minor increase in the 
size of the compiled program.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
64
Chapter 18: Declarations
Inline Functions (C99)
 Declaring a function to be i nl i ne doesnt 
actually force the compiler to inline the 
function.
 It suggests that the compiler should try to make 
calls of the function as fast as possible, but the 
compiler is free to ignore the suggestion.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
65
Chapter 18: Declarations
Inline Definitions (C99)
 An inline function has the keyword i nl i ne as one of 
its declaration specifiers:
i nl i ne  doubl e  aver age( doubl e  a,   doubl e  b)
{
r et ur n  ( a  +  b)   /   2;
}
 aver age has external linkage, so other source files 
may contain calls of aver age.
 However, the definition of aver age isnt an external 
definition (its an inline definition instead).
 Attempting to call aver age from another file will be 
considered an error.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
66
Chapter 18: Declarations
Inline Definitions (C99)
 There are two ways to avoid this error.
 One option is to add the word st at i c to the 
function definition:
st at i c i nl i ne doubl e aver age( doubl e a, doubl e b)
{
r et ur n  ( a  +  b)   /   2;
}
 aver age now has internal linkage, so it cant be 
called from other files.
 Other files may contain their own definitions of 
aver age, which might be the same or different.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
67
Chapter 18: Declarations
Inline Definitions (C99)
 The other option is to provide an external 
definition for aver age so that calls are permitted 
from other files.
 One way to do this is to write the aver age
function a second time (without using i nl i ne) 
and put this definition in a different source file.
 However, its not a good idea to have two versions 
of a function: we cant guarantee that theyll 
remain consistent when the program is modified.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
68
Chapter 18: Declarations
Inline Definitions (C99)
 A better approach is to put the inline definition of 
aver age in a header file:
#i f ndef   AVERAGE_H
#def i ne  AVERAGE_H
i nl i ne  doubl e  aver age( doubl e  a,   doubl e  b)
{
r et ur n  ( a  +  b)   /   2;
}
#endi f
 Lets name this file aver age. h.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
69
Chapter 18: Declarations
Inline Definitions (C99)
 Next, well create a matching source file, 
aver age. c:
#i ncl ude  " aver age. h"
ext er n doubl e aver age( doubl e a, doubl e b) ;
 Any file that needs to call the aver age function 
can include aver age. h.
 The definition of aver age included from 
aver age. h will be treated as an external 
definition in aver age. c.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
70
Chapter 18: Declarations
Inline Definitions (C99)
 A general rule: If all top-level declarations of a 
function in a file include i nl i ne but not 
ext er n, then the definition of the function in that 
file is inline.
 If the function is used anywhere in the program, 
an external definition of the function will need to 
be provided by some other file.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
71
Chapter 18: Declarations
Inline Definitions (C99)
 When an inline function is called, the compiler has 
a choice:
 Perform an ordinary call (using the functions external 
definition).
 Perform inline expansion (using the functions inline 
definition).
 Because the choice is left to the compiler, its 
crucial that the two definitions be consistent.
 The technique just discussed (using the 
aver age. h and aver age. c files) guarantees 
that the definitions are the same.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
72
Chapter 18: Declarations
Restrictions on Inline Functions (C99)
 Restrictions on inline functions with external 
linkage:
 May not define a modifiable st at i c variable.
 May not contain references to variables with internal 
linkage.
 Such a function is allowed to define a variable that 
is both st at i c and const .
 However, each inline definition of the function 
may create its own copy of the variable.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
73
Chapter 18: Declarations
Using Inline Functions with GCC (C99)
 Some compilers, including GCC, supported inline 
functions prior to the C99 standard.
 Their rules for using inline functions may vary 
from the standard.
 The scheme described earlier (using the 
aver age. h and aver age. c files) may not 
work with these compilers.
 Version 4.3 of GCC is expected to support inline 
functions in the way described in the C99 
standard.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
74
Chapter 18: Declarations
Using Inline Functions with GCC (C99)
 Functions that are specified to be both st at i c
and i nl i ne should work fine, regardless of the 
version of GCC.
 This strategy is legal in C99 as well, so its the 
safest bet.
 A st at i c i nl i ne function can be used within 
a single file or placed in a header file and included 
into any source file that needs to call the function.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
75
Chapter 18: Declarations
Using Inline Functions with GCC (C99)
 A technique for sharing an inline function among 
multiple files that works with older versions of 
GCC but conflicts with C99:
 Put a definition of the function in a header file.
 Specify that the function is both ext er n and i nl i ne.
 Include the header file into any source file that contains 
a call of the function.
 Put a second copy of the definitionwithout the words 
ext er n and i nl i nein one of the source files.
 A final note about GCC: Functions are inlined 
only when the - Ocommand-line option is used.
Copyright 2008 W. W. Norton & Company.
All rights reserved.
76