News for hackers. Stuff that matters.
Re:Modern C++ for C Programmers: part 5 by stephencanon on Wednesday July 25, 2018 @09:50AM (#17609190)
Return value optimization is absolutely allowed in C, and ~all compilers do it. It's not commonly talked about because in C, there can be no side-effects when constructing or copying a struct, so there's nothing to discuss. It just happens automatically and there's no observable change in program behavior.
Re:Modern C++ for C Programmers: part 5 by BeeOnRope on Wednesday July 25, 2018 @05:31PM (#17613046)
No C doesn't have RVO in the C++ sense. Sure C can optimize the copies implied by "returning values" in the same way they can optimize other copies or anything at all, if the observable behavior is the same, due to "as if" - but that's not RVO (as it is discussed in C++). It doesn't even need a special name: it's just plain old optimization.

RVO is a very specific optimization that has its own language in the standard (which is notable since the standard is pretty much silent on the vast majority of optimizations) and it is special precisely because it allows the optimization to occur even if it changes observable behavior. C does not have it, and compilers must compile the some code more conservatively because of it: e.g., if the address of return values escape in the caller and/or callee, a C compiler must ensure that the program always observes distinct addresses for distinct objects in the source, but in C++ one is free to observe that two apparently different objects are the same.

Now, sure, at least 90% of actual RVO is about eliminating constructors and destructors with side effects - which C doesn't have and so RVO simply doesn't apply most of the time: but one shouldn't conclude that "C has RVO", rather "C mostly doesn't need RVO, and in the cases were it could use it, it is not allowed and must be more conservative than C++".

Re:Modern C++ for C Programmers: part 5 by ajross on Wednesday July 25, 2018 @10:59AM (#17609768)
C compilers can do copy ellision when inlining code as long as the result is identical. That's not quite the same thing as RVO, which deliberately relaxes the notion of "identical result" such that it's possible to write C++ code to detect whether or not RVO was actually performed. That's not possible in C (or shouldn't be).
Re:Modern C++ for C Programmers: part 5 by stephencanon on Wednesday July 25, 2018 @12:13PM (#17610370)
It's possible that I'm missing something, but I believe that the result is necessarily identical in C, because there can be no observable side-effect of a struct copy in the C abstract machine.
Re:Modern C++ for C Programmers: part 5 by BeeOnRope on Wednesday July 25, 2018 @05:49PM (#17613197)
No, it is not necessarily identical in C, because even though you don't have constructors or destructors, you can make an address comparison to check whether two objects are identical.

For example the following code:

https://godbolt.org/g/ikD6bi

where the address of the caller's variable that will take the return value is passed along to the function returning it. Within the callee, f1 and f2 must be different objects in C, but not in C++.

All decent compilers compile this in C++ with only a single object, so sink() will receive identical objects. Most compilers "deoptimize" this in C since sink cannot receive identical objects: two objects are created so f1 and f2 have different addresses, and a copy is performed from f2 to the return value f1.

Due to a bug, clang mis-compiles this and applies the C++ RVO to C. So you maybe you are right: you can get RVO in C, but only due to a compiler bug!

Re:Modern C++ for C Programmers: part 5 by stephencanon on Wednesday July 25, 2018 @06:05PM (#17613351)
Ah, yes, that's a nice example.
Re:Modern C++ for C Programmers: part 5 by 8xde0wcNwpslOw on Wednesday July 25, 2018 @02:54PM (#17611804)
Don't quote me on this, but I think padding bytes might have different values in certain cases.
Re:Modern C++ for C Programmers: part 5 by a1369209993 on Wednesday July 25, 2018 @03:01PM (#17611857)
I'm fairly sure it's always undefined behavior to observe those differences, so while it's possible in practice, it'd never work in theory.
Re:Modern C++ for C Programmers: part 5 by e12e on Wednesday July 25, 2018 @05:49PM (#17613198)
> while it's possible in practice, it'd never work in theory.

Hah, sounds like you nailed the emergent philosophy of C there... :-)

Re:Modern C++ for C Programmers: part 5 by SidiousL on Wednesday July 25, 2018 @12:38PM (#17610583)
I tried to find an example that contradicts what you said, but I can't find any. Here's an online example which can be compiled as both C and C++ and I obtain exactly the same assembly using both clang and gcc. Maybe somebody can tweak this example to force the C compiler not to perform the optimization.

https://godbolt.org/g/7Ewun7

Re:Modern C++ for C Programmers: part 5 by BeeOnRope on Wednesday July 25, 2018 @05:51PM (#17613217)
See my reply to the parent poster for an example where RVO applies in C++ but not C, leading to better code in the C++ case. The key is to let the address of the objects involved escape: otherwise "as if" will let C (and C++ even without RVO) optimize away the copies anyways, since they are not observable in that case.
Re:Modern C++ for C Programmers: part 5 by jcelerier on Wednesday July 25, 2018 @10:25AM (#17609473)
No, C has much less RVO allowed than C++. I provided an example of this here the last time : https://news.ycombinator.com/item?id=17216250
Re:Modern C++ for C Programmers: part 5 by stephencanon on Wednesday July 25, 2018 @12:11PM (#17610357)
From what I can see, the example you list there is just a missed optimization in the C compilers you tested. It's absolutely allowed, and clang trunk is happy to do it in C-mode, for example.
Re:Modern C++ for C Programmers: part 5 by petters on Wednesday July 25, 2018 @12:55PM (#17610760)
There could be some more fundamental differences due to the requirement that different objects require different pointers that prevent some optimizations.