Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I specify an integer constant by its bytes?

Tags:

c++

c++11

elf

I'm using C++11 on a project of mine and was wondering how best to represent the ELF magic number. I'm not a fan of hex literals, so I was looking for something better than:

const uint32 ELF_MAGIC_NUMBER = 0x7F454c46; // 0x7F, E, L, F

So, I tried to write:

const uint32 ELF_MAGIC_NUMBER = { 0x7F, 'E', 'L', 'F' };

but the compiler complains that there are too many items in the initializer list, which is understandable, although annoying.

Is there any way to write an integer literal in terms of its bytes? I feel like the first option, while it works, is not as readable at the second.

like image 218
Alex Reinking Avatar asked Dec 27 '13 23:12

Alex Reinking


Video Answer


2 Answers

Since you can afford C++11, you could just define a little constexpr helper, which would enable compile-time evaluation:

#include <cstdint>

constexpr std::uint32_t from_bytes(char b1, char b2, char b3, char b4)
{
    return b4 + 
           (static_cast<std::uint32_t>(b3) << 8) + 
           (static_cast<std::uint32_t>(b2) << 16) + 
           (static_cast<std::uint32_t>(b1) << 24);
}

This way, your code won't look much different from the original version:

const std::uint32_t ELF_MAGIC_NUMBER = from_bytes(0x7F, 'E', 'L', 'F');

int main()
{
    static_assert(ELF_MAGIC_NUMBER == 0x7F454c46, "!");
}

Here is a live example.

like image 140
Andy Prowl Avatar answered Oct 23 '22 13:10

Andy Prowl


Many compilers have this little known feature: multi-char character literals.

uint32 ELF_MAGIC_NUMBER = '\177ELF';

You'll have to use octal numbers for the non char, I'm afraid.

Ah, almost forgot! The meaning of that is compiler dependent, so I wouldn't do it.

But if you can use C++11 you can use constexpr and user-defined literals:

constexpr uint32_t operator "" _mc (const char *str, size_t len)
{
    return len==4? 
         (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3] : 
         throw "_mc literal must be of length 4";
}

constexpr uint32_t ELF_MAGIC_NUMBER = "\177ELF"_mc;

This has the nice feature that you can use string concatenation to use hexadecimal characters:

constexpr uint32_t ELF_MAGIC_NUMBER = "\x7F""ELF"_mc;
like image 37
rodrigo Avatar answered Oct 23 '22 12:10

rodrigo