2.2 Dive into C
1. Header Files
A header file in C is a file with a .h
extension that contains declarations of functions, variables, macros, and data types, which can be shared across multiple .c
source files. The actual definitions (i.e., the implementation of functions) go into .c
files, while header files allow the code to be reused and organized efficiently.
1.1 What Goes in a Header File?
- Function Declarations (Prototypes):
- These specify the function signature but not the body. They allow the compiler to know about a function’s existence before it is defined.
// Example of function declaration in a header filevoid greet(void);
// Note that the function definition (function signature + body)// is in the correponding .c file
#include <stdio.h>// Example of function definition in a corresponding .c filevoid greet(void) { printf("Hello World.");}
-
Macros
- Common macros, constants, or inline code can be defined in a header file.
#define PI 3.14159#define SQUARE(x) (x * x) -
Data Type Definitions (
typedef
):- Custom data types can be declared in the header for reuse in various
.c
files.
- Custom data types can be declared in the header for reuse in various
typedef struct { int x; int y;} Point;
- Global Variables Declarations:
- Declaring external global variables that are defined in other
.c
files.
- Declaring external global variables that are defined in other
extern int global_counter;
- Structure Definitions:
- You can define structures, unions, and enums that need to be shared between files.
typedef struct { char name[50]; int age;} Person;
- Include/Header Guards:
- Header files typically use include/header guards to prevent multiple inclusions in a single compilation unit, which would lead to redefinition errors.
#ifndef MYHEADER_H#define MYHEADER_H
// Declarations and definitions go here
#endif
1.2 How to Use a Header File
- Create a Header File:
- You create a
.h
file (e.g.,myheader.h
) that contains the declarations needed by other files.
- You create a
#ifndef MYHEADER_H#define MYHEADER_H
void greet(void); // Function declaration
#endif
- Include the Header in Source Files:
- In your
.c
source files, you include the header file with the#include
directive.
- In your
#include <stdio.h>#include "myheader.h" // Including the custom header file
int main() { greet(); // Calling the function declared in the header return 0;}
- Provide Definitions in a Separate
.c
File:- The actual implementation of the functions declared in the header goes in the
.c
file.
- The actual implementation of the functions declared in the header goes in the
#include <stdio.h>#include "myheader.h"
void greet(void) { printf("Hello, World!\n");}
1.3 Why Use Header Files?
- Code Reusability: Functions and variables declared in a header file can be used in multiple
.c
files. - Code Organization: Header files help organize large programs by separating declarations from implementation.
- Modularity: Changes to a declaration in a header file automatically propagate to all files that include it.
2. Static Functions / Variables
In C, the static
keyword is used to limit the scope and lifetime of both functions and variables. Its behavior differs slightly depending on whether it is applied to a function or a variable.
2.1 Static Functions
A static function is a function that is limited in scope to the file where it is defined. This means that a static function cannot be called from other files, even if they include the function’s declaration in a header file.
- File-level scope: A static function is visible only within the file it is defined in, making it “private” to that file.
Example
#include <stdio.h>
static void myFunction() { printf("This is a static function.\n");}
int main() { myFunction(); // This works because we're in the same file. return 0;}
// file2.cextern void myFunction();
int main() { myFunction(); // Error: myFunction is not visible here due to static. return 0;}
In this example, myFunction()
is declared static
, so it is accessible only within file1.c
. Attempting to use it in file2.c
results in an error.
Another Example
#include <stdio.h>
void checkDate();
/* You can declare this function (prototype) in anyother .c file and use it without any issue. */void nonstatic_testMain(){ printf("nonstatic_testMain\n");}
/* This function is private to main.c file. Cannot bedeclared (prototype) and used in any other .c file.An error will be reported by the linker if you do sobecause the linker cannot locate the definition inmain.c file. Remember it is hidden! therefore util.ccannot see it! */static void static_testMain(){ printf("nonstatic_testMain\n");}
/* static function declaration (prototype) can be movedto a seperate header file. But still, static will stillmake the function private to where it is defined */
int main(){ checkDate(); return 0;}
/* compile the code withgcc -Wall -ansi -pedantic main.c util.c -o prog */
#include <stdio.h>
void nonstatic_testMain();
void static_testMain();
void checkDate(){ nonstatic_testMain(); static_testMain(); /* ERROR: Cannot use private function of main.c. Linker will complain */ printf("checkDate()\n");}
2.2 Static Variables
2.2.1 Static Local Variables
A static local variable inside a function retains its value across multiple calls to the function. Normally, a local variable’s value is lost when the function exits, but a static variable persists for the lifetime of the program.
- Persistence: The value of a static local variable is retained between function calls.
- Initialization: Static local variables are initialized only once, and if not explicitly initialized, they are set to
0
by default.
Example of Static Local Variable:
#include <stdio.h>
void incrementCounter() { static int counter = 0; // This variable is initialized only once counter++; printf("Counter: %d\n", counter);}
int main() { incrementCounter(); // Output: Counter: 1 incrementCounter(); // Output: Counter: 2 incrementCounter(); // Output: Counter: 3 return 0;}
Here, counter
is a static local variable, so it retains its value across multiple calls to incrementCounter()
.
Another Example
#include <stdio.h>
int add(){ /* This statement will only be execute once and once only when the function add() is invoked for the first time. The static local variable num will stay alive until the end of the program (not the function-end). */ static int num = 0;
num = num + 1; printf("Result: %d\n", num); /* will print 1, 2, 3 if add() is invoked thrice */
return num;}
int add2(){ static int num; num = 0;
num = num + 1; printf("Result: %d\n", num); /* will print 1, 1, 1 if add() is invoked thrice */
return num;}
int main(){ checkDate(); add(); add(); add(); add2(); add2(); add2(); return 0;}
2.2.2 Static Global Variables
A static global variable (a variable declared outside of any function but marked as static
) has its scope limited to the file in which it is declared, similar to static functions.
- File-level scope: The static global variable can only be accessed within the file where it is declared.
Example
#include <stdio.h>
static int globalCounter = 0; // This variable is limited to this file.
void incrementGlobalCounter() { globalCounter++; printf("Global counter: %d\n", globalCounter);}
// file2.cextern int globalCounter; // This won't work because globalCounter is static.
int main() { globalCounter = 10; // Error: globalCounter is not visible here. return 0;}
Here, globalCounter
is static, so it cannot be accessed from file2.c
.
2.3 Key Differences
-
Scope:
- Static Function: Only visible within the file where it’s defined.
- Static Local Variable: Visible only within the function, but persists across function calls.
- Static Global Variable: Visible only within the file where it’s defined.
-
Lifetime:
- Static Local Variable: Retains its value between function calls.
- Static Global Variable: Exists for the duration of the program but is confined to the file scope.
2.4 Use Cases
- Static functions: Useful for encapsulating functions and preventing them from being used outside the file, ensuring file-level modularity.
- Static variables: Useful when you need to maintain state across function calls (static local) or restrict the visibility of global variables to the file (static global).