"Pop quiz! What will the following program return?<p><pre><code> int main() {
printf("Hello World!\n");
}
</code></pre>
Easy, right? It's gotta be 0, because since at least ISO/IEC 9899:1999 (aka "C99"), main shall implicitly return 0 if you, the forgetful programmer, didn't bother to explicitly return a value:"<p>As hobbyist programer I write small programs and run them on older computers, running a variety of OS. Among other things, I use -std=c89 for various reasons. Thus, I know the answer to the pop quiz, for me, is not zero. Being forgetful triggers a warning.<p><pre><code> cat <<eof >1.c
int main() {
printf("Hello World!\n");
}
eof
cc -Wall -std=c89 -pedantic -ansi 1.c
./a.out
1.c: In function 'main':
1.c:4:10: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
4 | printf("Hello World!\n");
| ^~~~~~
1.c:4:10: warning: incompatible implicit declaration of built-in function 'printf'
1.c:1:1: note: include '<stdio.h>' or provide a declaration of 'printf'
+++ |+#include <stdio.h>
1 |
1.c:5:2: warning: control reaches end of non-void function [-Wreturn-type]
5 | }
| ^</code></pre>
As a learning exercise I try to silence the warnings one by one.<p>Instead of just including <stdio.h>, which teaches me nothing, I find the prototype string and insert it the .c file using a short script something like the following<p><pre><code> #!/bin/sh
test $# = 1||exec echo usage: $0 function
grep -r " $1(" /usr/include/* 2>/dev/null|sed 's/.*://;s/ *//'
</code></pre>
This enables me to learn that the printf protoype uses __restrict instead of restrict, and consequently a portability note:<p>On Linux, __restrict is defined in /usr/include/features.h<p>On NetBSD, __restrict is defined in /usr/include/sys/cdefs.h<p>Now, with the printf() prototype included<p><pre><code> sed \$r1.c <<eof >2.c
int printf(const char *restrict, ...);
eof
cc -Wall -std=c89 -pedantic -ansi 2.c
./a.out
2.c: In function 'main':
2.c:5:2: warning: control reaches end of non-void function [-Wreturn-type]
5 | }
| ^
</code></pre>
The -std=c89 option enables me to learn to use exit(). Using return statement will also suppress the warning. For the main() function however, cf. a subroutine inside main(), I use exit() instead of return.<p><pre><code> sed 4r2.c <<eof >3.c
exit(0);
eof
cc -Wall -std=c89 -pedantic -ansi 3.c
./a.out
3.c: In function 'main':
3.c:5:35: warning: implicit declaration of function 'exit' [-Wimplicit-function-declaration]
5 | printf("Hello World!\n");exit(0);
| ^~~~
3.c:5:35: warning: incompatible implicit declaration of built-in function 'exit'
3.c:1:1: note: include '<stdlib.h>' or provide a declaration of 'exit'
+++ |+#include <stdlib.h>
1 |
</code></pre>
Find the prototype for exit() and add it in, instead of just blindly including <stdlib.h>.<p><pre><code> sed 2r3.c <<eof >4.c
void exit(int);
eof
cc -Wall -std=c89 -pedantic -ansi 4.c
./a.out</code></pre>