Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Standard compliance of a C macro

Tags:

c++

c

I have this little gem here (idea shamlessly stolen from the C-FAQ):

/* A lot of checks omitted to get rid of the architectures with a "weird" endianness */
/*...*/
#define MP_ENDIANESS ( (0x41424344ul == *(uint32_t*)"ABCD") ? MP_BIG_ENDIAN : MP_LITTLE_ENDIAN )

Is it compliant (that is not an undefined behaviour) to the new current standard (C-18 at the time this question has been asked) and if yes, which of the older ones support it, too?

Is it also standard compliant C++? (Yes, I know about std::endian)

like image 468
deamentiaemundi Avatar asked Oct 03 '19 18:10

deamentiaemundi


2 Answers

It has several issues:

  • uint32_t isn't guaranteed to exist
  • "ABCD", an array decaying to a char* (C) /char const* (C++), is not guaranteed to be suitably aligned for uint32_t*. If it isn't, the cast is UB
  • if the cast went through, the deref (*(uint32_t*)"ABCD") is a strict aliasing violation (UB)

You might want to simply do something like this instead:

#if !__cplusplus
    #define LITTLE_ENDIAN_EH() (*(char*)&(int){1});
#else
    //C++ doesn't have compound literals
    static int const LITTLE_ENDIAN_EH_ = 1;
    #define LITTLE_ENDIAN_EH() (*(char*)&LITTLE_ENDIAN_EH_)
#endif

(Works because char will exist, can alias anything, and has minimal alignment requirements.)

All the macros, including your attempts, have the disadvantage of being unsuitable for preprocessor conditionals (#if ...) or in contexts where an integer constant expression is required (case labels, array sizes, bitfield sizes), but when used elsewhere, modern compilers will generally treat the result as a compile time constant as far as optimized assembly output is concerned.

like image 122
PSkocik Avatar answered Oct 16 '22 09:10

PSkocik


This is not defined behavior in C++. *(uint32_t*)"ABCD" treats the memory of "ABCD" as if it were an uint32_t, but since it isn't really, this is a strict aliasing violation and undefined behavior.

like image 26
NathanOliver Avatar answered Oct 16 '22 08:10

NathanOliver