Imagine somebody thought omitting the return statement and doing whatever the compiler likes is a good feature to have.
Like Scala?
There is no 'printf'
31–40 of 158 posts
Re: There is no 'printf'
#32Moar please. I'm loving these counterintuitive C optimization gotchas lately[1]. They are like little brain teasers. 1. https://news.ycombinator.com/item?id=28930271
About a year ago there was something of a "joke isEven() implementation discourse" on Twitter, which eventually evolved a sort of informal optimizer abuse contest. For example: https://twitter.com/zeuxcg/status/1291872698453258241 https://twitter.com/jckarter/status/1428071485827022849
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 0The first one I'm less certain about. The only thing I can think of is that the compiler deduces an upper limit of INT_MAX - 1 to avoid signed overflow, and then somehow figuring out the true/false pattern from there? Still a bit of a gap in my understanding there.
Re: There is no 'printf'
#33Earlier quoted context omitted.
Per the man: > puts() and fputs() return a nonnegative number on success, or EOF on error. r is the result of the write, if it’s nonzero the write failed and thus so did puts.
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.
Re: There is no 'printf'
#34This is a bit like saying there is no '+'; Because if you put in return 1+2+3; And look at the assembly code, you will see that the compiler generated something like return 6; The compiler is allowed to take advantage of the standard to substitute in more efficient code that does the same thing. IIRC, for C++, it would actually be ok if std::vector was implemented completely as a compiler intrinsic with no actual hea…
Re: There is no 'printf'
#35Earlier quoted context omitted.
> more efficient code that does the same thing In this case, it produces a different result.
It produces a different ub, which is ub. Furthermore observability would be defined in terms of the C abstract machine, “observing” by decompiling the program is out of scope.
> But what if you're not using C99 or newer?
UB - that takes all the fun out of it.
Re: There is no 'printf'
#36C 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".
One of my favorite parts of rust as someone who uses it for deeply embedded systems is the separation of core and std (where core is the subset of std that only requires memcpy, memset, and one other I'm forgetting). The rest of the standard library is ultimately an optional part of the language with compiler optimizations focused on general benefits rather than knowing at the complier how something like printf works. no_std is such a nicer env than the half done ports of newlib or pdclib that everyone uses in C embedded land.
Re: There is no 'printf'
#37Quick 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'
#38Earlier quoted context omitted.
About a year ago there was something of a "joke isEven() implementation discourse" on Twitter, which eventually evolved a sort of informal optimizer abuse contest. For example: https://twitter.com/zeuxcg/status/1291872698453258241 https://twitter.com/jckarter/status/1428071485827022849
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…
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'
#39Re: There is no 'printf'
#40Earlier quoted context omitted.
About a year ago there was something of a "joke isEven() implementation discourse" on Twitter, which eventually evolved a sort of informal optimizer abuse contest. For example: https://twitter.com/zeuxcg/status/1291872698453258241 https://twitter.com/jckarter/status/1428071485827022849
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…
in | out
----------
0b000 | 1
0b001 | 0
0b010 | 1
0b011 | 0
0b100 | don't care
.
.
.
MAX | don't care
The compiler just chooses the most efficient way it knows to get the filled out entries correct which happens to be: in | ~in[0]
----------
0b000 | 1
0b001 | 0
0b010 | 1
0b011 | 0
0b100 | 1
.
.
.
MAX | 1
It would have been just as valid to do: in | in[2] or ~in[0]
----------
0b000 | 1
0b001 | 0
0b010 | 1
0b011 | 0
0b100 | 1
0b101 | 1
.
.
.
MAX | 1
The first function's table looks like: in | out
----------
0b000 | 1
0b001 | don't care
0b010 | don't care
.
.
.
MAX | don't care
And the compiler still likes the even check in this case, which makes sense.