Live data from Hacker News

There is no 'printf'

netmeister.org

141–150 of 158 posts

Re: There is no 'printf'

#141

Earlier quoted context omitted.

How is it different? Why do you draw the line at I/O function?

Because it doesn't really matter how the program calculates mathematical functions as long as the result is correct. Whether it's a function or an instruction, it's inconsequential. I/O on the other hand is a lot more interesting. They're a very common source of undefined behavior, bugs and interception via custom shared objects. I'd rather the compiler touched them as little as possible. Actually I'd rather not use…

For me, it doesn't matter whether printf("hello\n") works via a call to printf or a call to puts. If those 6 characters I specified are written to standard output, I don't care how it was done.

Of course I care if I want to use the value returned by printf, but if my code uses that value the optimization isn't performed.

I think the semantic gap between assembly language and C is much wider than a lot of people realize. I wonder if a language somewhere in the middle of that gap would be useful to some people. (It probably wouldn't be useful to me.)

Re: There is no 'printf'

#142
post #135
post #95

Earlier quoted context omitted.

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 specifi…

If you specify "-std=c90", all you are saying, for this case, is that you don't care what value is returned. If you don't care, then zero is as good as any other value, so there is no reason for the compiler to have a different code path for that case. There are always good reasons not to have poorly exercised code paths.

Re: There is no 'printf'

#143

Earlier quoted context omitted.

What about datetime, random, system, etc?

They're all system calls that are better served by using operating functions directly. I'm not sure how the compiler could possibly optimize those away though. Maybe the random function could become a very untrustworthy instruction?

Random number generation generally isn't handled by system calls. It's just computation. (Some languages do provide support for hardware [pseudo-]random number generation. C doesn't.)

More generally, using system calls directly for things like getting the current time makes sense only if you don't care about portability.

C can support both portable and non-portable code. Both are important.

I get the impression that C is too high-level, and assembly language is too tedious, to fully support your requirements. I sympathize with your situation, but it's not one that most programmers share.

Re: There is no 'printf'

#144

Earlier quoted context omitted.

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].

You can just send them to argue with Ritchie himself :)

"C is quirky, flawed, and an enormous success."

https://www.bell-labs.com/usr/dmr/www/chist.html

Re: There is no 'printf'

#145
post #142
post #135

Earlier quoted context omitted.

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 specifi…

If you specify "-std=c90", all you are saying, for this case, is that you don't care what value is returned. If you don't care, then zero is as good as any other value, so there is no reason for the compiler to have a different code path for that case. There are always good reasons not to have poorly exercised code paths.

Earlier versions of gcc didn't support C99 or later at all. Making reaching the closing "}" do an implicit "return 0;" was a new language feature, and it was tied to the (non-default) "-std=c9x" or later "-std=c99" option.

Some existing code might have depended (foolishly IMHO) on the arbitrary non-zero value returned from main. Even if that's not the case, if you're programming in C90, having your program indicate that it failed is a good reminder to add the "return 0;".

I've never bothered to check exactly how "gcc -std=c90" handles this, but having it intentionally return a non-zero value in C90 mode would have been a good choice, since it would make the bug of omitting the return or exit more visible. gcc can also warn about not returning a value from a non-void function.

Whatever it returns in C90 mode, it's not a bug, and so the gcc maintainers have probably decided that they have more important things to do than change the behavior. They might have made a different choice if they were implementing "-std=c90" from scratch today.

Re: There is no 'printf'

#146
post #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…

> It does not cause undefined behavior.

I haven't read the standard. I am just stating what TFA says. So are you saying it is inaccurate?

Re: There is no 'printf'

#147
post #137

Earlier quoted context omitted.

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…

> It does not cause undefined behavior. I haven't read the standard. I am just stating what TFA says. So are you saying it is inaccurate?

Yes, it's inaccurate.

Here's what the C90 standard says:

5.1.2.2.3 Program termination

A return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument. If the main function executes a return that specifies no value, the termination status returned to the host environment is undefined.

Re: There is no 'printf'

#148
post #64

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)

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.

Any such expectation is unfounded. The C90 standard says:

"A return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument. If the main function executes a return that specifies no value, the termination status returned to the host environment is undefined."

Re: There is no 'printf'

#149
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.

As far as I understand, there is no “expected behavior of main without a return” under ANSI; it’s undefined behavior as (according to this version of the C standard) a function with an int return type must return an int. The fact that it happens to return the result of last function call is more-or-less a coincidence because the compiler doesn’t bother to clear out or reuse the return value register. If this seems un…

No, it's not undefined behavior. Only the status returned to the host environment is undefined. (And in C99 and later, the status is 0.)

As for your example:

int foo(int x) { if (x >= 0) return 123; if (x that has undefined behavior only if the caller uses the value. (That's to cater to ancient C code written before the void type was introduced.)

Re: There is no 'printf'

#150
post #145
post #142

Earlier quoted context omitted.

If you specify "-std=c90", all you are saying, for this case, is that you don't care what value is returned. If you don't care, then zero is as good as any other value, so there is no reason for the compiler to have a different code path for that case. There are always good reasons not to have poorly exercised code paths.

Earlier versions of gcc didn't support C99 or later at all. Making reaching the closing "}" do an implicit "return 0;" was a new language feature, and it was tied to the (non-default) "-std=c9x" or later "-std=c99" option. Some existing code might have depended (foolishly IMHO) on the arbitrary non-zero value returned from main. Even if that's not the case, if you're programming in C90, having your program indicate t…

What do you suppose has changed between when they did, and today, that could lead to a different choice?
Post reply on HN