Scope, Storage Duration, and Linkage in C
an Introduction |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
char
, int
, void
)inline
)auto
,
extern
, register
,
static
)struct
, union
,
enum
)// Type Specifier int i; // Type Specifier with a Modifier double grades[10]; void error_exit(); // Type Specifier with a Type Qualifier volatile int size; // Type Specifier with a Type Qualifier and Modifier const int *fp;
#include <stdio.h> int main(void) { n += 5; printf("%d\n", n); return 0; }
n
is not declared
in the scope of main()
#include <stdio.h> int n = 0; int main(void) { n += 5; printf("%d\n", n); return 0; }
n
has file scope
#include <stdio.h> int n = 0; int main(void) { int n; n += 5; printf("%d\n", n); return 0; }
n
with file
scope and an n
with local scope
n
is not
initialized.#include <stdio.h> int n = 0; int main(void) { int n = 1; n += 5; printf("%d\n", n); return 0; }
n
with file
scope and an n
with local scope
malloc()
) and
ends at deallocation (e.g., free()
)#include <stdio.h> int total(int x) { static int total = 0; total += x; return total; } int main(void) { total(5); total(10); printf("%d\n", total(15)); return 0; }
static
specifier
can be used in the declaration of a varaible with block scope
library.h
#ifndef LIBRARY_H #define LIBRARY_H int net_price(int price, int discount); static int validate(int n); #endif
library.c
#include "library.h" int net_price(int price, int discount) { return validate(price - discount); } static int validate(int n) { if (n < 0) return 0; else return n; }
driver.c
#include "library.h" int main(void) { int i, j; i = validate(-5); j = net_price(6, 2); }
validate()
in
main()
is undefined because validate()
has internal linkage#include <stdio.h> int n = 0; int main(void) { extern int n; n += 5; printf("%d\n", n); return 0; }
// A definition (and implicit declaration) of a function int max(int a, int b) { if (a > b) return a; else return b; } // A definition (and implicit declaration) of a variable with file scope int total = 0;
extern
== Yes:
extern
== No or static
== Yes):
= 0
or = {0}
if there is no definition in the same translation
unit)// A declaration with external linkage extern int i; // A definition with external linkage int total = 0; // A definition with internal linkage static const char *university = "JMU"; // A tentative definition with external linkage int j; // A tentative definition with internal linkage static int k;
account.h
and
account.c
driver.c
that
uses the libraryaccount.h
#ifndef ACCOUNT_H #define ACCOUNT_H #define ACCT_OK 0 #define ACCT_INVALID 1 #define ACCT_CLOSED 2 int acct_status; #endif
account.c
#include "account.h" // Use acct_status
driver.c
#include "account.h" // Use acct_status
account.h
is in
both translation unitsmultiple definition of 'acct_status'
because acct_status
has been defined in both
translation units
account.h
#ifndef ACCOUNT_H #define ACCOUNT_H #define ACCT_OK 0 #define ACCT_INVALID 1 #define ACCT_CLOSED 2 // Don't define acct_status since that caused the problem #endif
account.c
#include "account.h" // Use acct_status
driver.c
#include "account.h" // Use acct_status
'acct_status' was not declared in this scope
account.h
#ifndef ACCOUNT_H #define ACCOUNT_H #define ACCT_OK 0 #define ACCT_INVALID 1 #define ACCT_CLOSED 2 // Don't define acct_status #endif
account.c
#include "account.h" int acct_status; // Use acct_status
driver.c
#include "account.h" // Use acct_status
account.c
will compile but
driver.c
won'taccount.h
#ifndef ACCOUNT_H #define ACCOUNT_H #define ACCT_OK 0 #define ACCT_INVALID 1 #define ACCT_CLOSED 2 extern int acct_status; #endif
account.c
#include "account.h" // Use acct_status
driver.c
#include "account.h" // Use acct_status
acct_status
is only declared in account.h
, not defined
undefined reference to 'acct_status'
because it has been declared but not defined
account.h
#ifndef ACCOUNT_H #define ACCOUNT_H #define ACCT_OK 0 #define ACCT_INVALID 1 #define ACCT_CLOSED 2 extern int acct_status; #endif
account.c
#include "account.h" int acct_status = ACCT_OK; // Use acct_status
driver.c
#include "account.h" // Use acct_status