Imagine somebody thought omitting the return statement and doing whatever the compiler likes is a good feature to have.
Not that odd if you know the evolution of the language... and what it actually means for modern programmers. The very first C compilers ran on a PDP-11 in just a few dozen kilobytes of memory. The entire emphasis was on minimalism, and that meant that things like type enforcement was left to the human. One of the things the earliest language was missing was the "void" type. If you didn't give a return type to a funct…
There is no 'printf'
61–70 of 158 posts
Re: There is no 'printf'
#62Re: There is no 'printf'
#63Jeeze, don't tell him about semihost-supporting compilers like IAR or Keil, where printf can be one of several different things depending on your target or what configuration options are set for debugging.
Re: There is no 'printf'
#64Quick Summary: The C compiler optimizer replaces printf("Hello World!\n") with puts("Hello World!\n") and the implicit return from main() changes from 13 (the return value of printf) to 10 (the return value of puts)
Re: There is no 'printf'
#65> But what if you're not using C99 or newer? If you're using C90, but under an implementation that supports C99, that implementation should obey all the new rules in all areas where there is no conflict between C90 and C99. The ISO C90 standard is obsolescent, so the fact that dropping off the end of main with no return value is an unspecified termination status is an obsolescent requirement (or non-requirement). It…
clang doesn't do this as far as I can tell -- though it's difficult to be sure, since returning a status of 0 is valid C90 behavior.
Re: There is no 'printf'
#66Earlier quoted context omitted.
Not that odd if you know the evolution of the language... and what it actually means for modern programmers. The very first C compilers ran on a PDP-11 in just a few dozen kilobytes of memory. The entire emphasis was on minimalism, and that meant that things like type enforcement was left to the human. One of the things the earliest language was missing was the "void" type. If you didn't give a return type to a funct…
OK, but this doesn’t do wonders as a counterargument that C is just a big pile of historical baggage.
But sure, I wouldn't recommend anyone choose C as a language for new software unless they have an extremely good reason, or if you really love stuff like implementing every data structure you use from scratch and using void* as a kind of wildly unsafe generic.
Re: There is no 'printf'
#67Earlier quoted context omitted.
OK, those are horrifying and fascinating, and they basically break my brain. Is there a explanation somewhere of why the first one "works"? The second one I think is the compiler assuming the default case will never be hit since it'll result in infinite recursion, which is UB under C++, so it's basically assuming 0 The first one I'm less certain about. The only thing I can think of is that the compiler deduces an upp…
My guess: since overflowing int is UB, and the only value of n that stops the recursion is zero, the compiler assumes that n must be zero and checks accordingly. That doesn’t explain why it uses test dil, 1 instead of test dil, dil or cmp 0 or whatever.
Re: There is no 'printf'
#68 int main() {
printf("Hello World!\n");
}
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:"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.
cat 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 '' or provide a declaration of 'printf'
+++ |+#include
1 |
1.c:5:2: warning: control reaches end of non-void function [-Wreturn-type]
5 | }
| ^
As a learning exercise I try to silence the warnings one by one.Instead of just including , which teaches me nothing, I find the prototype string and insert it the .c file using a short script something like the following
#!/bin/sh
test $# = 1||exec echo usage: $0 function
grep -r " $1(" /usr/include/* 2>/dev/null|sed 's/.*://;s/ *//'
This enables me to learn that the printf protoype uses __restrict instead of restrict, and consequently a portability note:On Linux, __restrict is defined in /usr/include/features.h
On NetBSD, __restrict is defined in /usr/include/sys/cdefs.h
Now, with the printf() prototype included
sed \$r1.c 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 | }
| ^
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. sed 4r2.c 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 '' or provide a declaration of 'exit'
+++ |+#include
1 |
Find the prototype for exit() and add it in, instead of just blindly including . sed 2r3.c 4.c
void exit(int);
eof
cc -Wall -std=c89 -pedantic -ansi 4.c
./a.outRe: There is no 'printf'
#69So, why does puts do "return r ? EOF : '\n';"? Some backwards compatibility? Or is there a logical reason for that?
That particular implementation probably returns the result of the last fputc() or equivalent that it called. puts() returns EOF (typically -1) on error, or some unspecified non-negative value on success. fputc() returns EOF on error or the written character, treated as an unsigned char and converted to int, on success. Don't expect all puts() implementations to do the same thing. For example, the glibc implementation…
Re: There is no 'printf'
#70Earlier quoted context omitted.
It's arbitrary. The article shows an implementation that returns 10 (ASCII '\n'). But the spec says it doesn't matter, so you should only be using it to test >0 for success.
The correct implementation is obviously to return 1 on success !