Practical C Issues:! Preprocessor Directives, Multi-file Development, Makefiles. CS449 Fall 2017

Similar documents
#include. Practical C Issues: #define. #define Macros. Example. #if

Practical C Programming

The Preprocessor. CS 2022: Introduction to C. Instructor: Hussam Abu-Libdeh. Cornell University (based on slides by Saikat Guha) Fall 2011, Lecture 9

Chapter 7: Preprocessing Directives

A Fast Review of C Essentials Part II

Errors During Compilation and Execution Background Information

C and C++ 2. Functions Preprocessor. Alan Mycroft

C: Program Structure. Department of Computer Science College of Engineering Boise State University. September 11, /13

2 Compiling a C program

Modifiers. int foo(int x) { static int y=0; /* value of y is saved */ y = x + y + 7; /* across invocations of foo */ return y; }

CSci 4061 Introduction to Operating Systems. Programs in C/Unix

Intermediate Programming, Spring 2017*

CS 326 Operating Systems C Programming. Greg Benson Department of Computer Science University of San Francisco

#include <stdio.h> int main() { printf ("hello class\n"); return 0; }

P.G.TRB - COMPUTER SCIENCE. c) data processing language d) none of the above

Control flow and string example. C and C++ Functions. Function type-system nasties. 2. Functions Preprocessor. Alastair R. Beresford.

G52CPP C++ Programming Lecture 6. Dr Jason Atkin

Compiler Theory. (GCC the GNU Compiler Collection) Sandro Spina 2009

Rule 1-3: Use white space to break a function into paragraphs. Rule 1-5: Avoid very long statements. Use multiple shorter statements instead.

Follow us on Twitter for important news and Compiling Programs

Outline. Compiling process Linking libraries Common compiling op2ons Automa2ng the process

CMPSC 311- Introduction to Systems Programming Module: Build Processing

Have examined process Creating program Have developed program Written in C Source code

C for Engineers and Scientists: An Interpretive Approach. Chapter 7: Preprocessing Directives

Gabriel Hugh Elkaim Spring CMPE 013/L: C Programming. CMPE 013/L: C Programming

CSE 374 Programming Concepts & Tools

Unit 4 Preprocessor Directives

CMPSC 311- Introduction to Systems Programming Module: Build Processing

Topic 6: A Quick Intro To C

Executables and Linking. CS449 Spring 2016

Topic 6: A Quick Intro To C. Reading. "goto Considered Harmful" History

CSE 333 Lecture 7 - final C details

Basic C Programming (2) Bin Li Assistant Professor Dept. of Electrical, Computer and Biomedical Engineering University of Rhode Island

COMP322 - Introduction to C++ Lecture 02 - Basics of C++

Contents Lecture 3. C Preprocessor, Chapter 11 Declarations, Chapter 8. Jonas Skeppstedt Lecture / 44

Formal Methods for C

Executables and Linking. CS449 Fall 2017

Lectures 5-6: Introduction to C

Macros and Preprocessor. CGS 3460, Lecture 39 Apr 17, 2006 Hen-I Yang

INDEX. Figure I-0. Listing I-0. Table I-0. Symbols.DIRECTIVE (see Assembler directives)? preprocessor operator 3-34

CS240: Programming in C

SISTEMI EMBEDDED. The C Pre-processor Fixed-size integer types Bit Manipulation. Federico Baronti Last version:

0x0d2C May your signals all trap May your references be bounded All memory aligned Floats to ints round. remember...

Intermediate Programming, Spring 2017*

PRINCIPLES OF OPERATING SYSTEMS

Programming. Projects with Multiple Files

OBJECT ORIENTED PROGRAMMING USING C++

Oregon State University School of Electrical Engineering and Computer Science. CS 261 Recitation 2. Spring 2016


The C Preprocessor (and more)!

Slide Set 5. for ENCM 339 Fall Steve Norman, PhD, PEng. Electrical & Computer Engineering Schulich School of Engineering University of Calgary

Come and join us at WebLyceum

Appendix A. The Preprocessor

Macros in C/C++ Computer Science and Engineering College of Engineering The Ohio State University. Lecture 33

Lecture 2: C Programming Basic

Chapter 11 Introduction to Programming in C

Lecture 2: C Programm

SISTEMI EMBEDDED. The C Pre-processor Fixed-size integer types Bit Manipulation. Federico Baronti Last version:

Basic C Programming. Bin Li Assistant Professor Dept. of Electrical, Computer and Biomedical Engineering University of Rhode Island

Lecture 03 Bits, Bytes and Data Types

The C Preprocessor Compiling and Linking Using MAKE

PROGRAMMAZIONE I A.A. 2017/2018

Deep C. Multifile projects Getting it running Data types Typecasting Memory management Pointers. CS-343 Operating Systems

Final CSE 131B Spring 2004

Lecture 10: Potpourri: Enum / struct / union Advanced Unix #include function pointers

Chapter 11 Introduction to Programming in C

Reviewing gcc, make, gdb, and Linux Editors 1

SISTEMI EMBEDDED. The C Pre-processor Fixed-size integer types Bit Manipulation. Federico Baronti Last version:

CSCI-243 Exam 1 Review February 22, 2015 Presented by the RIT Computer Science Community

Conditional Compilation

C Compilation Model. Comp-206 : Introduction to Software Systems Lecture 9. Alexandre Denault Computer Science McGill University Fall 2006

C Preprocessor. Prabhat Kumar Padhy

CS 261 Fall C Introduction. Variables, Memory Model, Pointers, and Debugging. Mike Lam, Professor

C Programming. The C Preprocessor and Some Advanced Topics. Learn More about #define. Define a macro name Create function-like macros.

Lecture 3: C Programm

CSE 374 Programming Concepts & Tools. Brandon Myers Winter 2015 C: Linked list, casts, the rest of the preprocessor (Thanks to Hal Perkins)

QUIZ. What are 3 differences between C and C++ const variables?

Chapter 11 Introduction to Programming in C

independent compilation and Make

CS2141 Software Development using C/C++ Compiling a C++ Program

Appendix. Grammar. A.1 Introduction. A.2 Keywords. There is no worse danger for a teacher than to teach words instead of things.

Programs. Function main. C Refresher. CSCI 4061 Introduction to Operating Systems

COMsW Introduction to Computer Programming in C

211: Computer Architecture Summer 2016

Programming for Engineers C Preprocessor

CS3157: Advanced Programming. Outline

CSE 374 Programming Concepts & Tools

#include <stdio.h> int main() { char s[] = Hsjodi, *p; for (p = s + 5; p >= s; p--) --*p; puts(s); return 0;

A Fast Review of C Essentials Part I

Multiple file project management & Makefile

[Software Development] Makefiles. Davide Balzarotti. Eurecom Sophia Antipolis, France

Introduction to Supercomputing

Design and development of embedded systems for the Internet of Things (IoT) Fabio Angeletti Fabrizio Gattuso

CSCI 171 Chapter Outlines

1 You seek performance 3

Program Translation. text. text. binary. binary. C program (p1.c) Compiler (gcc -S) Asm code (p1.s) Assembler (gcc or as) Object code (p1.

The Make Utility. Independent compilation. Large programs are difficult to maintain. Problem solved by breaking the program into separate files

The Make Utility. Independent compilation. Large programs are difficult to maintain. Problem solved by breaking the program into separate files

Compiler, Assembler, and Linker

Conduite de Projet Cours 4 The C build process

Transcription:

Practical C Issues:! Preprocessor Directives, Multi-file Development, Makefiles CS449 Fall 2017

Multi-file Development

Multi-file Development Why break code into multiple source files? Parallel development involving multiple authors Quicker compilation (only compile modified file) Modularity (can reuse object file / library) Encapsulation (easier to read / maintain) Use smallest scope to enforce encapsulation Avoids polluting global namespace Minimizes scope of code to find all uses of symbol But sometimes scopes must cross file boundaries... Then same symbol must be declared in all relevant source files

Block / Function Scope Scope: Local (function or block of code) Lifetime: Automatic (duration of function) Static (duration of program) void foo( ) { } int x; // automatic static int y; // static x = y =

Internal Linkage Scope Scope: File Lifetime: Static (duration of program) static int x; void foo( ) { x = } Void bar( ) { x = }

External Linkage Scope Scope: Program (multiple files) Lifetime: Static (duration of program) extern used to declare vars in other files File A File B int x; extern int x; void foo() { } void foo(); B declares x and foo defined in A

Multi-file Example int x = 0; a.c b.c #include <stdio.h> int f(int y) { return x+y; } /* Declarations for symbols defined in other files */ extern int x; int f(int); int main() { x = 1; printf("%d", f(2)); return 0; }

Multi-file Example thoth$ gcc c a.c b.c thoth$ gcc a.o b.o thoth$./a.out 3

Pitfall: Missing Definitions a.c // Missing x definition b.c #include <stdio.h> int f(int y) { return y; } /* Declarations for symbols defined in other files */ extern int x; int f(int); int main() { x = 1; printf("%d", f(2)); } return 0;

Pitfall: Missing Definitions thoth$ gcc c a.c b.c thoth$ gcc a.o b.o./b.o: In function `main': b.c:(.text+0x6): undefined reference to `x' collect2: ld returned 1 exit status Linker cannot find x in symbol table when it tries to resolve x in x = 1; inside b.c

Pitfall: Missing Declarations int x = 0; a.c b.c #include <stdio.h> int f(int y) { return x+y; } /* Missing declarations for x and int f(int) */ int main() { x = 1; printf("%d", f(2)); } return 0;

Pitfall: Missing Declarations thoth$ gcc c a.c b.c./b.c: In function main :./b.c:5: error: x undeclared Compiler must know there is an externally defined x and its type is int to generate code

Declarations and Definitions Definitions: Put into individual C (.c) files Function definitions: ends up in text section of.o file Variable definitions: ends up in data section of.o file One symbol must be defined in only one C file Declarations: Put into header (.h) files è #included in any C file using the symbols Function declarations Variables declarations (using extern) Type definitions (e.g. struct definitions) #defines

Declarations and Definitions mymalloc.h // Declarations void *my_malloc(int size); mymalloc.c // Definitions static void *head; void my_free(void *ptr); Why wasn t head declared in mymalloc.h? void *my_malloc(int size) {... } void my_free(void *ptr) {... }

Including a Header File Insert header In each C file using my_malloc, my_free: main.c #include mymalloc.h // insert header int main() { my_malloc( ); } foo.c #include mymalloc.h // insert header int foo() { my_free( ); }

Compiling Multiple Files Compiling: gcc mymalloc.c main.c foo.c Why not also compile mymalloc.h? A. Header does not define any symbols Contains only declarations to help compiler Nothing to generate an object file out of (Code / data segment would be empty) Hence nothing to compile

Makefiles:! Easy Multi-file Development

Makefile A script interpreted by the GNU Make utility to build projects containing multiple files Design Goal: on a source / header file modification, perform the smallest set of actions required By expressing what files depend upon others Composed of a collection of rules which look like target: dependencies action That is a single <tab> before action, not spaces! Script invoked by: make <target> If no target given, first target in script built by default

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: mallocdriver.c mymalloc.h gcc c mallocdriver.c clean: rm f *.o malloctest

Dependency Graph malloctest mymalloc.o mallocdriver.o mymalloc.c mymalloc.h mallocdriver.c

Build from scratch Using a Makefile thoth $ ls Makefile mallocdrv.c mymalloc.c mymalloc.h thoth $ make gcc -c mymalloc.c gcc -c mallocdrv.c gcc -o malloctest mymalloc.o mallocdrv.o thoth $ make make: `malloctest' is up to date. Partial build after modifying mymalloc.c thoth $ touch mymalloc.c thoth $ make gcc -c mymalloc.c gcc -o malloctest mymalloc.o mallocdrv.o

Defining Variables in Makefiles Works like macros (text replacement) Syntax: <name> :=... or <name> =... Example: Instead of: malloctest: mymalloc.o mallocdriver.o gcc o malloctest mymalloc.o mallocdriver.o Can do: OBJECTS = mymalloc.o mallocdriver.o malloctest: $(OBJECTS) gcc o malloctest $(OBJECTS)

Automatic Variables $@: The file name of the target. E.g.: malloctest: $(OBJECTS) gcc o $@ $(OBJECTS) $<: The name of the first prerequisite. E.g.: mymalloc.o: mymalloc.c mymalloc.h gcc c $< $^: The names of all prerequisites. E.g.: malloctest: $(OBJECTS) gcc o $@ $^

Pattern Matching Character % is a wildcard for any string Example: %.o: %.c gcc c $< -o $@ What it means: For all targets matching <some string>.o Dependency is <that string>.c Action is gcc c <that string>.c o <that string>.o Rule is used to produce any.o file from.c file

Concise Makefile malloctest: mymalloc.o mallocdriver.o gcc -o $@ $^ %.o: %.c gcc -c $< -o $@ mymalloc.o: mymalloc.h mallocdriver.o: mymalloc.h clean: rm -f *.o malloctest

Make Utility Options Usage: make [-f makefile] [options] [targets] -f makefile: Makefile to interpret targets: Targets to be built Options: <name> = <value>: Define a variable. -C <dir>: Change to directory <dir> before building. -n: Dry run. Just print commands and don t execute. -d: Debug mode. Print verbose information.

Preprocecessor Directives:! Easy Manipulation of Source Code

#include Copies the contents of specified file into current file #include < >: file in standard include location Usually /usr/include #include : file in current directory or specified paths Paths specified using the I option If main.c has following includes: #include <stdio.h> #include myheader.h and is compiled using gcc I ~/local/include main.c stdio.h under /usr/include myheader.h under current directory or ~/local/include

#define Defines macros Macro: rule that specifies textual replacement of one string for another Often used to assign names to constants #define PI 3.1415926535 #define MAX 10 float f = PI; for(i=0;i<max;i++)

#define Good macros are generic (do not make assumptions about inputs) Good: #define MAX(a,b) (a > b)? a : b Only assumes a can be compared to b Not so good: #define SWAP(a,b) {int t=a; a=b; b=t;} Makes assumption that types are int Better #define SWAP(T,a,b) {T t=a; a=b; b=t;}

#if #if <condition known to preprocessor> // Some code #endif Preprocessor emits code between #if directive and #endif directive to the compiler only if condition is true Condition evaluated at preprocessing time (cf. C if statement is evaluated at execution time) What does preprocessor know? Constants (0, 1, 2, Linux, x86, ) Values of #defined variables Arithmetic (+, -, *, /, >, <, ==, &&,, )

Example #include <stdio.h> int main() { } #if 0 printf( This is not compiled\n ); I can doodle here when I am bored. #endif printf( This is compiled\n ); return 0;

Example 2 #include <stdio.h> #define LIBRARY_VERSION 7 int main() { } #if LIBRARY_VERSION >= 5 some_function_included_in_version_5(); printf( This is compiled\n ); #endif return 0;

#else #if <condition1> // Emitted if condition1 is true #elif <condition2> // Emitted if condition1 is false and condition2 is true #else // Emitted if neither is true #endif

#if defined #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 DEBUG int main() { } #if defined DEBUG printf( Some debug output\n ); #endif return 0;

#undef Undefines a macro: #include <stdio.h> #define DEBUG int main() { } #if defined DEBUG #endif printf( This is printed\n ); #undef DEBUG #if defined DEBUG printf( This is not\n ); #endif return 0;

Shortcuts for #if defined #if defined #ifdef #if!defined #ifndef

Uses of #if directive Enable / disable code specific to a library, OS, CPU, etc. Turn on / off different features of program Debugging: #ifdef DEBUG printf( ) #endif More flexible debugging //easier to modify functionality of PrintDebug later #ifdef DEBUG #define PrintDebug(args ) fprintf(stderr, args) #else #define PrintDebug(args ) #endif

Using #if to #include! Header Only Once Including same header twice can lead to compile errors Redefinition of the same struct type, etc.. Easy to stumble into with multiple levels of nested headers #ifndef _MYHEADER_H_ #define _MYHEADER_H_ Declarations only to be included once #endif

Command Line Defined Macros D: Defines variables from command line gcc o test DVERSION=5 test.c gcc o test DDEBUG test.c Allows tailoring of source code to specific versions and features from command line

Pre-Defined Macros Macro FILE LINE DATE TIME STDC GNUC VERSION unix i386 Meaning Current compiled file Current line number Current date Current time Defined if compiler supports ANSI C Defined if compiler is GNU C compiler Version of GNU C compiler Defined if OS is a UNIX compliant system Defined if CPU has x86 instruction set Many other macros

Other Preprocessor Details # - places quotes around macro argument #define CALL(f) { printf(#f); f(); } CALL(foo) { printf( foo ); foo(); } ## - concatenates two things in macro #define CALL(f) f ## _debug () CALL(foo) foo_debug() #error: Emit error message and exit #warning: Emit warning message #pragma: Change behavior of compiler

Error Direc4ve Example #include <stdio.h> #ifndef i386 #error "Needs x86 architecture." #endif int main() { // Some x86 specific code return 0; } >> gcc./error.c./error.c:3:2: error: #error "Needs x86 architecture. >> gcc m32./error.c Tests whether hardware plagorm is i386 (x86) and displays error Ini4ally fails because default compila4on target is x86_64 (and i386 is not defined) -m32 op4on changes target to x86, implicitly defining i386 #warning: allows compila4on but with warning message

Concatena4on Example #include <stdio.h> #ifdef i386 #define CALL(f) f ## _x86 () #else #define CALL(f) f ## _x86_64() #endif void foo_x86() { } printf( x86 binary executable\n"); void foo_x86_64() { } printf( x86_64 binary executable\n"); int main() { } CALL(foo); return 0; >> gcc./concat.c >>./a.out x86_64 binary executable >> gcc m32./concat.c >>./a.out x86 binary executable Calls different func4ons depending on target architecture When i386 macro is undefined: CALL(foo) calls foo_x86_64() When i386 macro is defined: CALL(foo) calls foo_x86() -m32 op4on implicitly passes -D i386 to preprocessor

Pragma Example #include <stdio.h> #pragma message "Compiling " FILE " using " VERSION int main() { } return 0; >> gcc./pragma.c./pragma.c:3: note: #pragma message: Compiling./pragma.c using 4.4.7 20120313 (Red Hat 4.4.7-4) Prints diagnos4c message during compila4on of file Note two pre-defined macros: FILE and VERSION Many more pragmas To control struct padding (e.g. #pragma pack(1) ) To control code op4miza4ons (e.g. #pragma omp parallel )