Advanced C Programming
from Expert C Programming: Deep C Secrets by
Peter van der Linden
CIS*2450
Advanced Programming Concepts
1
Topics
• Scope of symbol names
– 4 flavours
• Precedence of operators
– associativity
– syntax of declarations with multiple operators
2
Scope
• Definition
– Region over which you can access a variable by
name.
• There are 4 types of scope:
– Program scope … widest
– File scope
– Function scope
– Block scope … narrowest
3
Scoping Principle
• Always define a symbol in the narrowest
scope that works
• Reasons?
4
Program Scope
• The variable is active among all source files
that make up the executable.
– In C, all functions
– Global (extern) variables
• How does it work?
5
External Symbols
• Program scope symbols passed to linker
in .o file
– External definition, “extdef”
– External reference, “extref”
• In linked executable, each external symbol:
– Exactly 1 extdef, or else…
• “undefined external” “multiply defined external”
– Any number of extrefs
• substituted with final memory address of symbol
6
“Externals”
• Having “program scope” (external symbols)
is a common requirement
– assembly language
– all kinds of programming languages
– allows big program to be linked together out of
small modules
• Each language has own convention for
designating extdef & extref
7
Using Program Scope in C
• Function
– extdef: MARCFILE *useMarcFile(FILE *filep){…}
• definition only appears in one .c (marcutil.c)
– extref: MARCFILE *useMarcFile(FILE *filep);
• prototype declaration (.h) included in many .c files
• Variable (don’t have any in A1)
– extdef: MARCFILE *libfile;
• definition only appears in one .c, outside any function
• can initialize: type varname = initial_value;
– extref: extern MARCFILE *libfile;
• declaration appears anywhere, in/outside functions
8
File Scope
• A variable is active from its declaration
point to the end of the file.
– In C, static variables.
• If variable defined outside any function…
– would normally be “program scope” (global)
– “static” keyword keeps definition from being
passed to linker → doesn’t become external
9
Scope vs. Storage Class
• “Static” storage
– One copy of variable in executable program
– Applies to both program scope (global variables) & file
scope (“static” variables)
• Issue confused in C/C++ (real “deep secret” )
– Program scope (globals) are static in nature, but
without “static” keyword
– If you add “static” keyword, not global anymore!
10
Contrast Automatic Storage
• Associated with functions
– Arguments
– Local variables inside function
• Fresh temporary copy created on stack every time
function called
– Copy can be initialized (same value each time)
– Copy goes away when function returns to caller
– Allows recursion to work!
• “static” keyword changes local variable from
automatic to static storage class
– Initialization effective once, when program started
11
Function Scope
• Active from the beginning to the end of a
function.
– In C, only goto labels have function scope;
therefore you will never see them
12
Block Scope
• The variable is active from its declaration
point to the end of the block in which it was
declared.
– In C, these are local variables.
– Includes function’s parameters
13
Example
int i; /* Program scope */
static int j; /* File scope */
func ( int k ) { /* func is program scope,
k is block scope */
int m; /* Block scope */
….
}
/* which are static storage, auto? */
14
What Happens?
func() {
int a = 11;
{
int b = 10;
}
printf ( “%d %d\n”,a,b);
}
Won’t work!
The variable b is inside a block and therefore is not visible
to the rest of the function.
15
What Happens?
newfunc() {
int a = 11;
{
int b = 10;
printf ( “%d\n”,b);
}
printf ( “%d\n”,a);
}
WORKS!
16
Precedence of Operators
• Definition
– Determines the order in which operators are
evaluated.
– Operators are used to calculate values for both
numeric and pointer expressions
• Operators also have an associativity which
is used to determine the order in which
operands are grouped with operators.
17
Associativity
• Applies with 2 or more operators of same
precedence:
A op1 B op2 C op3 D
– Answers question: Which op is done first?
• Associativity can be either Left-to-Right or
Right-to-Left
18
Associativity
• Left-to-Right is most common
a + b – c;
– The + and – operators are both evaluated left-
to-right so the expression is
“a plus b, then subtract c”
– Equivalent to: (a + b) – c;
19
Associativity
• Right-to-Left is rare
a = b = c;
– This expression is read
“assign c to b, then to a”
– Equivalent to: a = (b = c);
– Meaningful because in C assignment operator
is an expression with a value
20
Problems with Precedence
• The precedence of some operators produces
problems when they create behaviours
which are unexpected.
21
Problems with Precedence
• Pointer to structure: *p.f
– Expectation: the field of what p points to
• (*p).f
– Actually: p.f gives a compile error
• *(p.f)
– Why: . is higher than *
– Note: The -> operator was made to correct this.
• p->f
22
Problems with Precedence
• int *ap[]
– Expectation: ap is a ptr to an array of ints
• int (*ap)[]
– Actually: ap is an array of pointers-to-int
• int *(ap[])
– Why: [] is higher than *
– Note: usually found in declarations.
23
Problems with Precedence
• int *fp()
– Expectation: fp is a ptr to a function returning
an int
• int (*fp)()
– Actually: fp is a function returning a ptr-to-int
• int *(fp())
– Why: () is higher than *
– Note: usually found in declarations.
24
Problems with Precedence
• c = getchar() != EOF
– Expectation: ( c = getchar() ) != EOF
– Actually: c = (getchar() != EOF)
• c is set equal to the true/false value
– Why: == and != have higher precedence than
assignment
25
Solution to Precedence Problems
• When in doubt…
Use parentheses!!!
• Better still, use parentheses anyway
– You may not be in doubt, but the next reader
may be
26