Live data from Hacker News

There is no 'printf'

netmeister.org

51–60 of 158 posts

Re: There is no 'printf'

#51

Earlier quoted context omitted.

Like Scala?

pretty sure scala (and most FP) has a well-defined "what to do when you leave off the return statement", not one that "is up to the compiler"

Not just FP. "Return the value of the last statement" is fairly common in imperative languages as well. Off the top of my head both Pearl and R do so as well.

Re: There is no 'printf'

#52
post #47

My compilers call printf just fine until you enable optimizations. -O0 adds references to printf, -O1 and higher switches to puts. I was kind of surprised about the fact that there was no warning about the missing return from main(). Normally, I'd expect the compiler to complain that a supposed int returning function does not return anything, because that would normally be undefined behaviour.

If you use GCC, enable -Wall and you'll get the diagnostic you want: /tmp/cp.c: In function 'main': /tmp/cp.c:4:1: warning: control reaches end of non-void function [-Wreturn-type] 4 | } | ^ If you use Clang, there is no diagnostic even with -Wall (or even -Weverything), but it looks like Clang always implements the implicit `return 0;` from C99 regardless of the `-std` setting.

To clarify, gcc -Wall only produces the warning with -std=c89/gnu89 (or GCC https://godbolt.org/z/Y7Wx5Y89q

Re: There is no 'printf'

#53
> 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 is possible for a conforming C90 implementation to return 0 in that case. A conforming C99 implementation must do that as a conformance requirement. There is no good reason for a C99 implementation behaving in a C90 compatibility mode to simply drop non-conflicting C99 requirements and revert a behavior such as this.

This should be a don't care issue, unless you're targeting a bona fide nothing-but-C90 implementation.

However, if you are telling your implementation to be C90, what reason are you doing that for? If it's not just some nerd gesture to show your contempt for C99, and you really care about portability to C90 implementations, then you probably want to be returning an explicit 0 from your main. Or even just to show contempt for C99, really, you should be returning that 0.

Re: There is no 'printf'

#55

Quick 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)

[deleted]

Re: There is no 'printf'

#57
There is no printf because there is no defined behavior.

To call a variadic function, you must have a prototype declaration in scope. (A correct prototype, needless to say.)

A non-prototype (i.e. old-style) declaration cannot declare a variadic function such as printf, so no such declaration can be correct.

If the function is not declared, then a declaration will effectively be assumed for the call, deduced from the types of the actual arguments, and a return value of int. In this case, the function will be "implicitly declared" to look something like

   int printf(char *);
but that is not the correct declaration for printf. Therefore, the call has undefined behavior.

The optimizer is allowed to rewrite this to:

   puts("daemons are running in your nose");
Likewise, it is allowed to rewrite it to:

   puts("Hello World!");

Re: There is no 'printf'

#59

There is no printf because there is no defined behavior. To call a variadic function, you must have a prototype declaration in scope. (A correct prototype, needless to say.) A non-prototype (i.e. old-style) declaration cannot declare a variadic function such as printf , so no such declaration can be correct. If the function is not declared, then a declaration will effectively be assumed for the call, deduced from the…

No, this optimization also happens when you `#include `. More accurately speaking, GCC (among others) evidently assumes that printf is the standard C library function no matter prototype is defined or not and replaces it with puts under the same assumption plus the following additional conditions:

- No other arguments are present.

- The format argument has no format specifiers and ends with `\n`.

- The return value is unused. (So `return printf("...\n");` would have prevented this optimization.)

Re: There is no 'printf'

#60

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 function, it just defaulted to returning "int". Therefore it was totally normal to have a function fail to return anything.

Since there was no distinction between "function returning int" and "function returning nothing", there was nothing stopping your program from using the value returned... it just meant you got whatever happened to be in the right register.

What does it mean for us today? Basically nothing. "void" was added 30+ years ago when ANSI C appeared. The language couldn't just break the old behavior but in any rational environment you enable enough compiler warnings to avoid these ancient quirks entirely:

  $ gcc -Wall -c a.c
  a.c:1:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
      1 | foo() {}
        | ^~~
  a.c: In function ‘foo’:
  a.c:1:8: warning: control reaches end of non-void function [-Wreturn-type]
      1 | foo() {}
        |        ^
Post reply on HN