News for hackers. Stuff that matters.
Re:1.5 is the midpoint between 0 and infinity in Ruby by plx211 on Friday November 27, 2020 @12:14PM (#25230482)
C++ :)

  #include <iostream>
  #include <limits>
  
  double midpoint(double first, double second) {
    auto firstAsInt = reinterpret_cast < int64_t & > (first);
    auto secondAsInt = reinterpret_cast < int64_t & > (second);
    auto mid = (secondAsInt + firstAsInt) / 2;
    return reinterpret_cast < double & > (mid);
  }
  
  int main() {
    std::cout
      << "1.0 <=> 1.5 = " << midpoint(1.0, 1.5) << "\n"
      << "0.0 <=> inf = " << midpoint(0.0, std::numeric_limits < double > ::infinity()) << "\n";
  
    return 0;
  }
Re:1.5 is the midpoint between 0 and infinity in Ruby by colejohnson66 on Friday November 27, 2020 @12:46PM (#25230826)
Rant:

Technically, that code invokes undefined behavior as you use `reinterpret_cast` to alias variables. The only standards conforming way (prior to `std::bit_cast`[0] in C++20) was to use `memcpy`.[a] `reinterpret_cast` was added for situations where code you have no control over requires a certain type, but you need to force it to take your variable.[b]

[a]: As `memcpy` (in addition to reinterpreting bits) copies the bits (although a compiler will most likely optimize it out), it doesn’t violate aliasing rules.

[b]: This also requires that the code you give your kludged variable to not read out those bits as what it thinks it is (because aliasing). Kindof pointless because: what’s the point of passing a variable that’s never read?

[0]: https://en.cppreference.com/w/cpp/numeric/bit_cast

Re:1.5 is the midpoint between 0 and infinity in Ruby by kazinator on Friday November 27, 2020 @03:08PM (#25232158)
memcpy certainly violates aliasing rules. You can access an object as an array of bytes, but you can't memcpy an object to one of a different type and then access it as that type without invoking undefined behavior.
Re:1.5 is the midpoint between 0 and infinity in Ruby by colejohnson66 on Friday November 27, 2020 @04:00PM (#25232528)
Not true. You actually can. Aliasing is about viewing the same bits as two different types (what `reinterpret_cast`, union-based type punning, and cast pointers do) `memcpy` copies the bits to a new location which doesn’t violate aliasing. I don’t have time to find the reference in the standard, but cppreference.com[0] says it’s ok:

> Where strict aliasing prohibits examining the same memory as values of two different types, std::memcpy may be used to convert the values.

[0]: https://en.cppreference.com/w/cpp/string/byte/memcpy

Re:1.5 is the midpoint between 0 and infinity in Ruby by kazinator on Friday November 27, 2020 @05:18PM (#25233056)
Who is cppreference.com? The domain registration is concealed, just like that of the other dubious site, cplusplus.com.

I don't see any such a claim about memcpy having magic powers in the N4659 C++ draft.

All it says is that the underlying bytes of an object can be copied to an array of char, unsigned char, or std::byte. Then if that array is copied back into the object, the object subsequently holds its original value.

Anything more about memcpy comes from C by reference, and that would be about the last document on Earth to grant definedness and portability to something like this.

Re:1.5 is the midpoint between 0 and infinity in Ruby by haberman on Friday November 27, 2020 @03:58PM (#25232516)
memcpy() by itself cannot violate aliasing rules. By definition, char can alias any object.

Whether you can access an object that has been memcpy()'d into is a separate question. I can't find specific language about this, but I strongly suspect that the result is implementation-defined or unspecified (not undefined), unless there is a possibility of a trap representation.

Re:1.5 is the midpoint between 0 and infinity in Ruby by kazinator on Friday November 27, 2020 @05:20PM (#25233074)
This remark doesn't appear to add anything to my original unedited comment, which includes the clarifying words "you can't memcpy an object to one of a different type and then access it as that type without invoking undefined behavior".
Re:1.5 is the midpoint between 0 and infinity in Ruby by bertr4nd on Saturday November 28, 2020 @01:29AM (#25235736)
My reading of section 8.2.1 suggests that it is not UB to copy bytes from an object of one type to an object of another type, and then to read the value of the second object, since it is explicitly allowed to access each object as bytes.
Re:1.5 is the midpoint between 0 and infinity in Ruby by kazinator on Saturday November 28, 2020 @12:46PM (#25239039)
It being well-defined to access an object as an array of bytes doesn't add up to it being well-defined to access a whole object as an lvalue of any type. Type aliasing rules do not work this in this constructive way.