Using the GNU C-Compiler (GCC)
Compiling and running a first C program
unsigned long result; unsigned long factorial(unsigned long n) { if (n>1) { return n*factorial(n-1); } else { return 1; } } int main() { result = factorial(4); printf("result = %ld\n", result); return 0; }
Compile (read but ignore the warning for the moment) and run the program with
$shell> gcc -Wall -std=c99 -o factorial factorial.c factorial.c: In function 'main': factorial.c:16:5: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration] printf("result = %ld\n", result); ^ factorial.c:16:5: warning: incompatible implicit declaration of built-in function 'printf' factorial.c:16:5: note: include '' or provide a declaration of 'printf' $shell> factorial result = 24 $shell>
Examine the generated assembly code
Check out the generated assembly code with
$shell> gcc -Wall -std=c99 -S -fomit-frame-pointer -fno-asynchronous-unwind-tables factorial.c factorial.c: In function 'main': factorial.c:16:5: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration] printf("result = %ld\n", result); ^ factorial.c:16:5: warning: incompatible implicit declaration of built-in function 'printf' $shell>
Note that the parameters -fomit-frame-pointer and -no-fasynchronous-unwind-tables are just used here for the sake of simplicity. The assembly code generated is stored in file factorial.s:
$shell> cat factorial.s .file "factorial.c" .comm result,8,8 .text .globl factorial .type factorial, @function factorial: subq $24, %rsp movq %rdi, 8(%rsp) cmpq $1, 8(%rsp) jbe .L2 movq 8(%rsp), %rax subq $1, %rax movq %rax, %rdi call factorial imulq 8(%rsp), %rax jmp .L3 .L2: movl $1, %eax .L3: addq $24, %rsp ret .size factorial, .-factorial .section .rodata .LC0: .string "result = %ld\n" .text .globl main .type main, @function main: subq $8, %rsp movl $4, %edi call factorial movq %rax, result(%rip) movq result(%rip), %rax movq %rax, %rsi movl $.LC0, %edi movl $0, %eax call printf movl $0, %eax addq $8, %rsp ret .size main, .-main .ident "GCC: (Debian 4.9.2-10) 4.9.2" .section .note.GNU-stack,"",@progbits $shell>
Examine the result of the C Preprocessor (CPP)
Check the output of the CPP for the C program
#define N 6 unsigned long result; unsigned long factorial(unsigned long n) { if (n>1) { return n*factorial(n-1); } else { return 1; } } int main() { result = factorial(N); printf("result = %ld\n", result); return 0; }
Use the option -E so that gcc just calls the CPP and then stops (so any other options for gcc can be omitted):
$shell> gcc -E factorial2.c # 1 "factorial2.c" # 1 "" # 1 " " # 1 "factorial2.c" unsigned long result; unsigned long factorial(unsigned long n) { if (n>1) { return n*factorial(n-1); } else { return 1; } } int main() { result = factorial(6); printf("result = %ld\n", result); return 0; } $shell>
Getting rid of the warning
-
First check the result of CPP (just to see once what the #include does)
-
Compile and run the program with gcc -Wall -std=c99 -o factorial3 factorial3.c
-
Compile and run the program with gcc -DN=10 -Wall -std=c99 -o factorial3 factorial3.c
#include <stdio.h> #define N 6 unsigned long result; unsigned long factorial(unsigned long n) { if (n>1) { return n*factorial(n-1); } else { return 1; } } int main() { result = factorial(N); printf("result = %ld\n", result); return 0; }
Types size_t and ptrdiff_t
-
Compile and run
#include <stddef.h> #include <stdio.h> #define N 6 size_t result; size_t factorial(size_t n) { if (n>1) { return n*factorial(n-1); } else { return 1; } } int main() { result = factorial(N); printf("result = %zu\n", result); printf("sizeof(result) = %zu\n", sizeof(result)); printf("&result = %zu\n", (size_t) &result); return 0; }
-
Complete the following code
#include <stddef.h> #include <stdio.h> size_t a, b, c; ptrdiff_t d, e, f; int main() { printf("a = %zu\n", a); printf("b = %zu\n", b); printf("c = %zu\n", c); // change the format string to correctly output variables of type ptrdiff_t printf("d = %zu\n", d); printf("e = %zu\n", e); printf("f = %zu\n", f); // output the addresses of a, b, .... // decrement a and d by one // output a and d return 0; }
-
Change the previous code such that variables a, ..., f are now local variables. Compile and run the code.