Download Preprocessor Directives, Multi-file Development, and Makefiles | CS 0449 and more Study notes Computer Science in PDF only on Docsity!
Practical C Issues:
Preprocessor Directives, Multi-file
Development, and Makefiles
David Kyle
Based on slides by Jonathan Misurda
#include
• Copies the contents of the specified file into
the current file
• < > indicate to look in a known location for
includes
• “ “ indicate to look in the current directory or
specified path
#include <stdio.h>
#include “myheader.h”
#define
• Textual Symbol Replacements
#define PI 3.
#define MAX 10
float f = PI;
for(i=0;i<MAX;i++) …
#define Macros
• Textual replacements with parameters:
• Good:
- #define MAX(a, b) (a > b)? a : b
• Not so good:
- #define SWAP(a,b) {int t=a; a=b; b=t;}
#if
• #if <condition that can be evaluated by the
preprocessor>
• What does preprocessor know?
– Values of #defined variables
– Constants
Example
#include <stdio.h>
int main()
#if 0
printf(“this is not printed\n”);
#endif
printf(“This is printed\n”);
return 0;
Example 2
#include <stdio.h>
#define VERSION 5
int main()
#if VERSION < 5
printf(“this is not printed\n”);
#endif
printf(“This is printed\n”);
return 0;
#else
#if
#elif
#else
#endif
#ifdef
• #if defined
– Checks to see if a macro has been defined, but
doesn’t care about the value
– A defined macro might expand to nothing, but is
still considered defined
Example
#include <stdio.h> #define MACRO int main() { #if defined MACRO printf(“this is printed\n”); #endif printf(“This is also printed\n”); return 0; }
#undef
• Undefines a macro:
#include <stdio.h> #define MACRO #undef MACRO int main() { #if defined MACRO printf(“this is not printed\n”); #endif printf(“This is printed\n”); return 0; }
Shortcuts
• #if defined → #ifdef
• #if !defined → #ifndef
File Scope
• “Global Variables” are actually limited to the
file
• extern maybe be used to import variables
from other files
File A
int x;
File B
extern int x;
Will refer to the same memory location
Example
a.c
int x = 0; int f(int y) { return x+y; }
b.c
#include <stdio.h> extern int x; int f(int); int main() { x = 5; printf("%d", f(0)); return 0; }
Compiling
gcc a.c b.c
./a.out
Static
a.c
static int x = 0; static int f(int y) { return x+y; }
b.c
#include <stdio.h> extern int x; int f(int); int main() { x = 5; printf("%d", f(0)); return 0; }
Compiling
gcc a.c b.c
/tmp/cccyUCUA.o(.text+0x6): In
function `main':
: undefined reference to `x'
/tmp/cccyUCUA.o(.text+0x19): In
function `main':
: undefined reference to `f'
collect2: ld returned 1 exit status
Header Files
• Usually only contain declarations
– Variable types
– Functions
– #defined macros
• Paired with an implementation file
Including a Header File Once
#ifndef MYHEADER_H
#define MYHEADER_H
…Definitions of header to only be included once
#endif
Headers and Implementation
mymalloc.h
void *my_nextfit_malloc(int size); void my_free(void *ptr);
mymalloc.c
static MallocInfo *head; void *my_nextfit_malloc(int size){ static MallocInfo *current; ... } void my_free(void *ptr) { ... }
Driver
• Driver program:
#include “mymalloc.h”
• Can now use those functions
• Compile:
gcc – o malloctest mymalloc.c mallocdriver.c
Makefiles
• Express what files depend upon others
• If any are modified, build smallest set required
Makefile
malloctest: mymalloc.o mallocdriver.o gcc – o malloctest mymalloc.o mallocdriver.o mymalloc.o: mymalloc.c mymalloc.h gcc – c mymalloc.c mallocdriver.o: mymalloc.h mallocdriver.c gcc – c mallocdriver.c
Dependency Graph
malloctest mymalloc.o mallocdriver.o mymalloc.c mymalloc.h mallocdriver.c