When you call printf you will actually issue a system call to write to stdout. Does stdlib directly issue system calls or does it use some inline assembly?
There is no 'printf'
111–120 of 158 posts
Re: There is no 'printf'
#112Earlier 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…
You are right. There are still a lot of so-called developers who cannot understand the concept of _undefined_ behavior.
Re: There is no 'printf'
#113Quick 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.
Which part of "undefined behavior" is not clear to you?
Re: There is no 'printf'
#114Earlier quoted context omitted.
Yeah, but I think the question was why EOF and "\n". It could as easily just return 1 or -1 for example, and it would make more sense I think.
puts() always adds a line termination so success means that '\n' is the last char for that implementation.
Re: There is no 'printf'
#115There 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…
> C compilers will typically have an escape hatch for envs like deeply embedded systems and kernels like gcc's -ffreestanding and -fno-builtin that says "but for real though, don't assume std lib functions exist or you know what they are based on the function's name". GCC requires standard library functions even on freestanding environments! It will still emit calls to those functions in certain circumstances. https:…
At least in C++, memcpy is special because it can be used to reinterpret bits of one object as another (in C you can use a union, and as of C++20 you can use the std::bit_cast function but it either just calls memcpy or it still needs its own magic)
double d = 1.0;
// type punning with union, allowed in C but not C++
union {
double d;
int64_t i;
} u;
u.d = d;
int64_t y1 = u.i; // undefined behaviour
// cast not allowed, not even reinterpret_cast
int64_t y2 = *reinterpret_cast(&x.d); // undefined behaviour
// memcpy - allowed! (if sizeof() params is the same)
int64_t y3;
static_assert(sizeof(y3) == sizeof(d));
memcpy(&y3, &d, sizeof(y3)); // well defined!
// C++20 bit_cast (probably just a convenience wrapper around memcpy)
int64_t y4 = std::bit_cast(d); // well defined
It seems wasteful to create a separate object in memory and copy bits from an old object, when all you want to do is reinterpret the bits of the existing chunk of memory. But memcpy doesn't do that (or at least might not) because it's optimised into a simple cast under the hood, but without the undefined behaviour. So memcpy looks like a standard library function but in a way it's more like a compiler instrinic. It would be possible to create a fully conformant version of memcpy, even in C++, by casting both parameters to char* which is special with respect to the aliasing rules, and copying char-by-char. But I suppose that would be harder to optimise into a simple cast.Re: There is no 'printf'
#116Earlier quoted context omitted.
Regardless of how you think a modern compiler in C99 mode should behave, the fact is that "gcc -std=c90" generates code that returns an arbitrary value from main if no return or exit is executed. 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.
I would say that is a bug. More than 22 years ago, ISO C introduced this requirement for a reason. The reason was almost certainly the desire to fix that issue for as many C programs as possible, and that there was no intent that there be an exceptions for C programs that happen to request C90 compatibility in their accompanying Makefile. An indeterminate termination status causes real problems like, oh, if those pro…
I wouldn't be surprised if there are old unix tools that relied on propagating the result of the last operation executed into main. In fact sometimes gcc has added explicit flags to enable this kind of "traditional" behaviour.
Clang was written well after C99, so it didn't make sense to implement the old traditional behaviour there in the first place.
Re: There is no 'printf'
#117When you call printf you will actually issue a system call to write to stdout. Does stdlib directly issue system calls or does it use some inline assembly?
What do you feel the difference is between "directly issuing system calls" and "some inline assembly"?
Re: There is no 'printf'
#118> 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…
Re: There is no 'printf'
#119My 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.
> 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 main() returns without a return statement, it is defined to return 0 by the specification. (§5.1.2.2.3 of http://www.open-std.org/jtc1/sc22/wg14/www/…
Re: There is no 'printf'
#120Earlier 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…