Thursday, October 3, 2019

Digest for comp.lang.c++@googlegroups.com - 25 updates in 4 topics

David Brown <david.brown@hesbynett.no>: Oct 03 09:48AM +0200

On 02/10/2019 15:54, Scott Lurndal wrote:
>> result of this function at compile time and use that in optimisation.
 
> Can it? How does that work when you're cross-compiling to a different
> architecture (like a microcontroller, for example)?
 
Try this on <https://godbolt.org>
 
 
static constexpr bool little_endianess(int num = 1) noexcept
{
return *reinterpret_cast<char*>(&num) == 1;
}
 
bool is_little_endian() {
return little_endianess();
}
 
 
 
You'll see gcc generate code such as:
 
is_little_endian():
movl $1, %eax
ret
 
 
This is, of course, an optimisation issue - not all compilers can handle
it, and you will need to enable optimisation. (And clang throws an
wobbly when you have a "reinterpret_cast" in a "constexpr" function.
You can just remove the "constexpr", since it doesn't help anyway.)
 
 
Compilers know their targets, and they know if they are targeting
little-endian or big-endian (or mixed-endian). They know that, even if
the cpu in question supports both endiannesses - binaries are generated
for only one endianness at a time.
David Brown <david.brown@hesbynett.no>: Oct 03 09:54AM +0200

On 02/10/2019 17:33, Barry Schwarz wrote:
> distinguish between the two cases, thus increasing the run time.
> Whether this is a significant consideration obviously depends on the
> code.
 
That is the /logical/ behaviour. In practice, a good compiler can
evaluate the function at compile time (even though it is not a constant
expression), and use this along with dead code elimination to remove the
run-time check and code that cannot be called.
 
(Since it logically has the the test, the unused branch of code still
has to be valid and compilable code, unlike when you use conditional
compilation with the preprocessor.)
 
> tested not to mention the nesting of && and || operations.
 
> OTOH, the function approach will fail if sizeof (int) is 1 (32-bit
> char).
 
You can happily combine the approaches:
 
# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) &&
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
(defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER ==
__BIG_ENDIAN) || \
(defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER ==
BIG_ENDIAN) || \
(defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) ||
(defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \
defined(__ARMEB__) || defined(__MIPSEB__) || defined(__s390__) ||
defined(__sparc__)
 
constexpr bool is_big_endian = true;
constexpr bool is_little_endian = false;
#define IS_BIG_ENDIAN 1
#define IS_LITTLE_ENDIAN 0
 
#else
 
constexpr bool is_big_endian = false;
constexpr bool is_little_endian = true;
#define IS_BIG_ENDIAN 0
#define IS_LITTLE_ENDIAN 1
 

No comments: