Live data from Hacker News

There is no 'printf'

netmeister.org

131–140 of 158 posts

Re: There is no 'printf'

#131

Earlier quoted context omitted.

> Do you also expect `sqrt(a)` to be `call sqrt` and not `sqrtss xmm0`? Of course. Who else is going to set errno when I pass negative a number?

So the compiler actually can't optimize because of legacy errno cruft? That's hilarious...

The compiler respects the C standard by default. According to it, puts() is the same as a printf() in some conditions, but sqrt() is not the same as the instruction.

If you don't like C, you can use a dialect of it by setting some flags: -fno-math-errno if you want to optimize sqrt anyway or -fno-builtin if you don't want the compiler to replace functions calls

Re: There is no 'printf'

#132

Earlier quoted context omitted.

That's exactly why we have specifications and standards - so that you don't have to guess and build mental models on flimsy assumptions, and know exactly what to expect.

The standard leaves so much stuff undefined or implementation defined there's no way to fully understand what's going on anyway. The only mental model you can form is of the very limited non-existent abstract machine, anything else you have to guess or go to great pains to avoid. It just isn't very useful to think in those terms, so many intuitions just aren't possible. Turns the language into this huge minefield. I'…

It sounds like what you really want is a high-level portable assembler. Which, to be fair, is one of the niches that C has occupied... but I'm not convinced it's optimally designed for that in general, even leaving UB aside.

But back in DOS days, there was something called Sphinx C--: https://bkhome.org/archive/goosee/cmm/c--doc.htm. A modern cross-arch reincarnation of that could be interesting.

Re: There is no 'printf'

#133

Earlier quoted context omitted.

OK, but this doesn’t do wonders as a counterargument that C is just a big pile of historical baggage.

But of course it is; did you expect anything else from a language that's almost 50 years old by now? It's not any different from, say, Common Lisp in that regard. This particular quirk is a few years older than C itself, actually! C was based on a similar language called B. Now B was originally written for PDP-7 and similar machines, which could only address words in memory, not individual bytes. So it was designed "…

You might be surprised. Half the time I say that, I get a comment like yours. The other half of respondents go on about how it’s nonsense and that C is perfectly [modern/simple/usable/reasonable].

Re: There is no 'printf'

#134

Earlier quoted context omitted.

https://stackoverflow.com/questions/3401156/what-is-the-use-...

Those answers were so frustrating to read. The question is explicitly asking "Why does this exist? When would you need it?" and yet most of the answers are "This is what it does." (sometimes with a few snide RTFMs thrown in for good measure).

that was exactly what i was asking for, i know how it works, but i would like to know how it is used by pros, (if used at all)

Re: There is no 'printf'

#135
post #95

Earlier quoted context omitted.

> 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. A compatibility with a code which depends on a behaviour of a previous version of the compiler is a reason enough. If compatibility is dropped you now have a very subtle bug which is hard to discover and understand unless you read about that partic…

There's no compatibility requirement here, because the old behavior is UB (both in theory and in practice).

The old behavior is not undefined behavior. In C90, falling off the end of main() returns an undefined status to the environment. The behavior of the program is otherwise well defined.

It's true that an implementation that follows the C99 and later requirements also conforms to the looser C90 requirements.

But if a compiler chooses not to do so, I don't see it as a bug. If I use "-std=c90" or equivalent, I'm specifically not asking for C99 or later semantics; I want the compiler to conform to the C90 standard. If I use "-std=c90" and my program assumes C99 or later semantics, that's a bug in my program, not in the compiler.

Re: There is no 'printf'

#136
post #64

Earlier quoted context omitted.

This sounds like a compiler optimizing bug, in that if the expected behavior of main without a return is that it will return the result of the last function call, then the last function in the main does use its return value and that should not be optimized.

Yeah honestly this blog post just seems to be highlighting a bug in gcc when it is compiling to an older version of C. Not sure why the author chose to frame it as some big point about the printf function.

When I do it on Linux, with gcc 10.2.1, it always returns 0, regardless of "-ansi", "-O2", or what-have-you. So, the author's experience is either peculiar to some old version of cc he used, or to a quirk of BSD.

The ISO C++ Standard dictates that if main fails to return a result, the program result is zero. And, g++ does this.

[Edit: I'm wrong... with "gcc -ansi -std=c90", with or without optimization, I get the 13! But not 10.]

Re: There is no 'printf'

#137

Tldr: Not returning a value from main() is undefined behavior in ANSI C. So compiler will do whatever it likes. It will return 0 or 42 or crash. In this case, gcc just replaces printf with something else it likes more.

No, it's not undefined behavior.

An aside: "ANSI C" usually refers to the C language as defined by the last standard directly published by ANSI, in 1989 -- but the ANSI organization has adopted each new ISO C standard after publication, so the C standard currently recognized by ANSI is ISO C 2017. We're not going to get people to change what they mean by "ANSI C", so I suggest referring instead to "C89" or "C90".

In C90, not returning a value from main() causes an undefined status to be returned to the environment. It does not cause undefined behavior. The behavior of such a program is otherwise well defined. (C99 and later made reaching the closing "}" of the main function do an implicit "return 0;" instead, a rule borrowed from C++.)

Re: There is no 'printf'

#138
post #2

Huh, this is pretty great; I've always fussily used fputs() when I'm just printing static strings, and apparently I don't need to bother, since the compiler will just do it for me.

It doesn't hurt to use (f)puts anyway when you intend to print a static string. This way you avoid extra overhead when using compilers that don't do this or building with flags that disable this optimization, as well as just clarify your intent.

Typically if you're calling printf you are not concerned about overhead.

Re: There is no 'printf'

#139
post #79

Earlier quoted context omitted.

Why is that a problem? (That's a serious question. I'm not suggesting that it isn't a problem. Apparently it is for you.) If I write printf("Hello, world\n"), all I care about is that those characters are written to the standard output stream when I run the program -- and that's all the language standard specifies. I rarely even look at the assembly or machine code. As someone else mentioned, "gcc -fno-builtin" inhib…

Because it's surprising and breaks our expectations. The author of this article clearly expected a call to printf to be present in the generated code. > all I care about is that those characters are written to the standard output stream when I run the program Sometimes people care about a lot more. Such as the ability to hook into a specific function or ensuring the compiler doesn't generate calls to certain function…

There is no "undefined behavior" in the sense that the C standard uses that term. The choice of which function to generate a call to in the generated assembly or machine code is not "behavior".

The way I think of it is that a C program specifies run-time behavior (which consists mostly of I/O). Any generated code is just a way to achieve that. C is not some kind of assembly language. The standard says nothing about CPU instructions or registers.

If you want to use C source code as a way to generate specific assembly or machine code, you'll have to go beyond what the language standard guarantees. If you need to do that, and you have an implementation that helps you with it, that's great.

I wonder if there's enough demand for a language that's independent of the target processor but still guarantees that a source call to a given function actually results in a call to that function, that a "+" operator results in a single addition CPU instruction, and so forth. It's not something I'd have any use for myself, but that doesn't mean it wouldn't be valuable. C isn't that language, but something similar to C might be.

Re: There is no 'printf'

#140

There is 'printf'. It's just that printf (and the rest of the standard library) is technically as much a part of the C language as the language grammar itself, and C compilers are welcome to use innate knowledge of those functions for optimizations. The other place you typically see this is calls to functions like memcpy/memset being elided to inline vector ops or CISC copies, or on simpler systems, large manual zero…

The "no_std" idea is one that has washed up over and over again, over the last half-century. ISO Standards typically call it "freestanding".

It has invariably failed to yield the promised benefits. It hangs around, anyway, cluttering up Standards. People waste endless hours proposing alterations to it for the next Standard edition, to be likewise ignored by implementers and informed users of whichever language.

I don't doubt that "no_std" will similarly float along, and even be taken up into whichever Standard takes hold, but it must identically fail to deliver to actual system developers, in practically useful terms, whatever benefit its promoters promise. A mirage may be beautiful, but it does not slake thirst.

Post reply on HN