There are two important classes of objects: functions and variables A DECLARATION is a statement which specifies how an object can be used - you give just the type or prototype of the object. function: extern int f(int x, char c); /* extern is optional */ variable: extern int x; /* without extern it would be a tentative definition */ A DEFINITION is a statement where the object is completely specified: function: return-type name (parameters) {statements making up function} variable: give type with initializer give type without initializer or 'extern' (if outside a function this is a tentative definition and is ignored if a definition with initializer is encountered) Storage is set aside when the definition is encountered. Functions can NEVER be defined inside other functions. The type of a function is int unless declared otherwise, but it is a good idea to declare int functions anyway: thus 'int main()' not 'main()'. All functions should be declared with a prototype or defined BEFORE use, to avoid problems with mismatched types or parameters. Variables may be declared as 'auto' or 'static' or 'extern' but only one can be used per declaration. Inside functions 'auto' is the default so keyword 'auto' is rarely seen. This most common kind of variable appears/disappears as functions start/return. 'auto' is not allowed on declarations outside functions. [ 'auto' may be replaced by 'register', but this not recommended. 'register' tells the compiler to try(!) to put variable in a register for fast access (but what makes you think you can do a better job than the compiler? You could easily slow down the program.) Taking address (&) of register variables is not allowed.] A variable that is ever declared as 'static' or 'extern' or appears outside functions has storage for it set aside ONCE and is initialized ONCE (to zero if no explicit initializer is given). Conceptually this is done just prior to program start. Only constants can be used as initializers! int x=4; int y; int main() { static int z=6; /* results in x = 4, y = 0, z = 6 */ A variable inside a function, which is not declared 'static' or 'extern' is 'auto'. Auto variables that are not initialized will contain garbage. Storage allocation and initialization is done each time the block containing the variable is started. Any expression, even function calls can be used as initializer, and it is equivalent to using a corresponding assignment at the start of the block. The latter is preferable, because it is easier to see. int f(int z) { int k; /* not so good but allowed */ int i=g(z-25)+7; double w; Two declaration modifiers may be used on variables: 'const' means "do not alter" and is useful in function parameters to prevent changes to the parameters. const char *const CCompiler="gcc"; /* means: const char: constant characters - cannot change chars in string const CCompiler: constant pointer - cannot make CCompiler point to any other string */ 'volatile' means "do not optimize access; get and store at each reference" /* wait for device to enter ready state */ while (device_control_and_status_register != READY) sleep(1); /* unless device... is declared volatile, it will be referenced only once. Yet another process will change stored value. */ SCOPE: where/when a name refers to same object. A variable declared at the start of a block or as a parameter only has block scope and suspends variables with same name given outside block. A variable declared outside a function has file scope - valid from where declared to end of file. int i=4; /* global i1 */ int main() /* i1 */ { /* i is 4 at program start i1 */ f(5); /* i1 */ /* i is still 4 i1 */ } /* */ int f(int i) /* new i: i2 */ { /* i is 5 i2 */ i=6; /* i2 */ /* i is 6 i2 */ { int i; /* new i: i3 */ /* i has garbage value i3 */ i=7; /* i3 */ /* i is 7 i3 */ } /* */ i; /* i is 6 i2 */ } Needless to say, using "i" as above is very poor style. To avoid confusion, you should use different names if a variable would suspend another one. Suspension is perhaps excusable in a very small block. Suspension of global variables, such as i1, is always poor style. [Using global variables is usually not good programming!] The real purpose of scoping rules is so that you do not need to check that the names you select are unique over an entire program: values outside will not be destroyed. This is especially an issue for loop control variables, i, j , k, for instance. LINKAGE: when same name declared in different scopes refers to same thing. Choices: External Linkage: names in several different files are same object. Internal Linkage: object is different from any outside the file. No Linkage: totally separate (example: parameters of a function and all auto variables have no linkage to anything outside function). 'static': never has external linkage 1) it is used to hide 'variables outside functions' and 'functions' in one file from all other files. These become static ONLY if the FIRST declaration in file has term 'static'. Subsequent 'extern' lines ignored. 2) 'variables inside functions' that are declared static have no linkage outside function. Similarly auto variables have no linkage. Variables declared 'extern' inside functions have extern linkage (but this is poor style, instead declare outside). Variables must be declared only once inside functions (but functions may be declared several times.) 'variables outside functions' and 'functions' which are not declared static the first time encountered in a file have external linkage and must have a definition in some file BUT ONLY if used in an expression in the program. (This rule and others above exist because of header files.) There must be only one definition. The compiler and linker are usually unable to catch all illegal or mismatched combinations. Always use header files to prevent problems.