0

I have predefined HEX values in my code. One of them is in the following.

#define ADDRESS1 0xD445556BD557
#define ADDRESS2 0xED612BDF113B

I also have an uint8_t array. Like

uint8_t MAC[6];

How can I compare this two things without writing a new function?

I have already tried

if(MAC == ADDRESS2)
Caglayan DOKME
  • 948
  • 8
  • 21
  • 2
    This question cannot be answered unless you specify what the byte order of `MAC` is compared to `ADDRESS1`. – user694733 Apr 30 '19 at 10:21
  • You should make a habit of adding an `u` suffix to all your hex integer constants, to dodge various hiccups caused by C's evil type system. Otherwise C can create very subtle bugs, see for example https://stackoverflow.com/questions/34182672/why-is-0-0x80000000). – Lundin Apr 30 '19 at 14:10

3 Answers3

8

Maybe you should use uint8_t array for ADDRESS* also, and use memcmp():

static const uint8_t ADDRESS1[] = {0xD4, 0x45, 0x55, 0x6B, 0xD5, 0x57};

if (memcmp(MAC, ADDRESS1, sizeof(ADDRESS1)) == 0)
SKi
  • 8,007
  • 2
  • 26
  • 57
  • 1
    I'm not sure if uint8_t's in this array shouldn't be in reversed order. It depends where this array comes from I believe. If this will work bad, try changing it. – alxio Apr 30 '19 at 10:48
  • This is an over-simplification. You need to take byte order and endianess in account. Especially if MAC is something coming from a communication protocol, which doesn't seem unlikely. – Lundin Apr 30 '19 at 14:08
2

How can I compare this two things without writing a new function?

You cannot compare a uint8_t array with a large integer without knowing the endianess. That is, will MAC[0] correspond to the most or least significant byte. There are 4 possible combinations:

  • If MAC[0] corresponds to the least significant byte and the CPU is little endian, you can simply use memcmp.
  • If If MAC[0] corresponds to the most significant byte and the CPU is big endian, you can simply use memcmp.
  • If MAC[0] corresponds to the most significant byte and the CPU is little endian, you need to mask out byte by byte from the large integer using bit shifts.
  • If MAC[0] corresponds to the least significant byte and the CPU is big endian, you need to mask out byte by byte from the large integer using bit shifts.

Example of masking:

// assuming MAC[0] is ms byte
for(size_t i=0; i<6; i++)
{
  uint8_t byte = (ADDRESS1 >> (i*8));
  if(MAC[6-1-i) != byte)
  { /* not equal, do something */ }
}

In addition, if the data is part of network protocols, you need to have the "network endianess" in mind. That is the endianess of the communication protocol, which is most often big endian.

Lundin
  • 195,001
  • 40
  • 254
  • 396
-4

You can try casting your array to pointer to long long and then check value under it. The problem is it's only 6*8 = 48 bit, but you can just use bitmask to remove extra bytes.

ADDRESS1 == (*((long long*)MAC) & 0xFFFFFFFFFFFF)

Full sample: https://ideone.com/kFc8h0

#define ADDRESS1 0xD445556BD557
#define ADDRESS2 0xED612BDF113B
static const uint8_t ADDRESS[6] = { 0x57, 0xD5, 0x6B, 0x55, 0x45, 0xD4 };

int main()
{
    if (ADDRESS1 == (*((long long*)ADDRESS) & 0xFFFFFFFFFFFF)) {
        std::cout << "ADDRESS1\n";
    }
    if (ADDRESS2 == (*((long long*)ADDRESS) & 0xFFFFFFFFFFFF)) {
        std::cout << "ADDRESS2\n";
    }
}

Note, that in sample I had to inverse bytes in ADDRESS array to to match the mask in ADDRESS1.

alxio
  • 128
  • 4
  • 2
    `*((long long*)MAC)` and `*((long long*)ADDRESS)` are dereferencing pointer of invalid type which are *strict aliasing violations*, and lead to *undefined behaviour*. Both are also dereferencing area larger than exist, which is also undefined behaviour. Masking after the dereference will not help with these issues. – user694733 Apr 30 '19 at 11:07
  • Yes, theoretically it is UB, but in practice I don't know any compiler, that will have problem with that, as memory available for program will be aligned to 32 bit, and I do not write on this two extra bytes anyway, so if other variables takes this it doesn't break anything. – alxio Apr 30 '19 at 11:28
  • All of the current generation of compilers will "have a problem". They will assume that any control flow path passing through `ADDRESS1 == (*((long long*)MAC) & 0xFFFFFFFFFFFF)` is unreachable, and delete it, which could completely mangle your program. – zwol Apr 30 '19 at 12:12
  • 1
    Worse yet, the array is 6 bytes and you make an 8 byte access. So there's three different, severe bugs here: strict aliasing violation, potential misaligned access and accessing invalid memory. In addition, this is a C question, not C++. – Lundin Apr 30 '19 at 14:15
  • “memory available for program will be aligned to 32 bit” is nonsense. Even if the memory for the section in which `ADDRESS` is stored is 32-bit aligned, there is no guarantee that `ADDRESS` will be 32-bit aligned. The compiler might well put the other string constant(s) `"ADDRESS1\n"` and/or `"ADDRESS2\n"` before it, resulting it it not being aligned. – Eric Postpischil Apr 30 '19 at 15:16