C Module System C and Data Structures Baojian
C Module System C and Data Structures Baojian Hua bjhua@ustc. edu. cn
Software System is Large n Practical software systems tend to be large and complex: n n Linux kernel consists of ~1000 K LOC So the general principals in designing large (even small) software systems are: n n dividing into manageable smaller ones separating specification (interface) from code (implementation)
Module System n Different styles of module systems in languages: n n ML signature and structure Java interface and class C header files (. h) and C files (. c) The next slides explain the details of the C module system via one example: n Complex number
Complex Number // Recall the definition of complex number c: // c = x + yi, where x, y in R, and i=sqrt(-1); // And some typical operations: // complex new. Complex (double x, double y); // complex add (complex c 1, complex c 2); // complex sub (complex c 1, complex c 2); // complex mult (complex c 1, complex c 2); // complex distance (complex c 1, complex c 2); // complex modus (complex c 1, complex c 2); // complex divide (complex c 1, complex c 2);
Complex Number: Interface— Types // In file “complex. h”: #ifndef COMPLEX_H #define COMPLEX_H // note that “struct complex” is not given typedef struct complex *complex; complex new. Complex (double x, double y); // other function prototypes are similar … #endif
Client Code // With this interface, we can write client code // that manipulate complex numbers. File “main. c”: #include “complex. h” int main () { complex c 1, c 2, c 3; c 1 = new. Complex (3. 0, 4. 0); c 2 = new. Complex (7. 0, 6. 0); c 3 = add (c 1, c 2); print. Complex (c 3); return 0;
Client Code // The client code now compiles: $gcc –c –std=c 99 –pedantic –Wall complex. h main. c // which produces main. o, which roughly looks // like: new. Complex(…) add(…) print. Complex(…) main. o Require an implementation of complex. h
Complex Number: Implementation#1—Types // In file “complex. c”: #include “complex. h” // We may choose to define complex type as: struct complex { double x; double y; }; // which stores the real and imaginary parts of // a complex number in fields x and y in a // structure.
Complex Number: Implementation#1—Operations // With this type definition, the “new. Complex” // function could be written as: complex new. Complex (double x, double y) { complex c = malloc (sizeof(*c)); c->x = x; c->y = y; return c; } // To call function “malloc”, we must include the // header file “stdio. h” #include <stdio. h>
Complex Number: Implementation#1—Operations // function “add ()”: complex add (complex c 1, complex c 2) { complex c = malloc (sizeof(*c)); c->x = c 1 ->x + c 2 ->x; c->y = c 1 ->y + c 2 ->y; return c; } // Leave other functions as programming // assignments. See the course page.
Linking // Now compiles file “complex. c”: $gcc –c –std=c 99 –pedantic –Wall complex. h complex. c // to produce file “complex. o”. Linking (simplified) new. Complex(…) add(…) print. Complex(…) main. o new. Complex(…) {} add(…){} print. Complex(…) {} a. out complex. o
Complex Number: Implementation#2—Types // In file “comp 2. c”: // Another definition of complex type: #include <stdio. h> #include “complex. h” struct complex { double a[2]; }; // which stores the real and imaginary parts of // a complex number in array element a[0] and // a[1] separately.
Complex Number: Implementation#2—Operations // With this type definition, the “new. Complex” // function could be written as: complex new. Complex (double x, double y) { complex c = malloc (sizeof(*c)); (c->a)[0] = x; (c->a)[1] = y; return c; }
Complex Number: Implementation#2—Operations // function complex add { complex c (c->a)[0] (c->a)[1] return c; } “add ()”: (complex c 1, complex c 2) = malloc (sizeof(*c)); = (c 1 ->a)[0] + (c 2 ->a)[0]; = (c 1 ->a)[1] + (c 2 ->a)[1]; // Leave other functions as programming // assignments. See the course page.
Linking // Now compiles file “complex. c”: $gcc –c –std=c 99 –pedantic –Wall complex. h comp 2. c // to produce file “comp 2. o”. Linking (simplified) new. Complex(…) add(…) print. Complex(…) main. o new. Complex(…) {} add(…){} print. Complex(…) {} a. out comp 2. o
Summary n The many benefits of modularity: n n n Reading the code: in small, separable pieces Testing the code: test each function separately Speeding up the code: focus only on the slow parts Extending the code: change only the relevant parts Compiling the code: compile each part separately
- Slides: 16