C преодоление ограничений псевдонима (объединения?)

Предположим, у меня есть образец исходного файла test.c, который я компилирую следующим образом:

$ gcc -03 -Wall

test. c выглядит примерно так ...

/// CMP128(x, y)
//
// arguments
//  x - any pointer to an 128-bit int
//  y - any pointer to an 128-bit int
//
// returns -1, 0, or 1 if x is less than, equal to, or greater than y
//
#define CMP128(x, y) // magic goes here

// example usages

uint8_t  A[16];
uint16_t B[8];
uint32_t C[4];
uint64_t D[2];
struct in6_addr E;
uint8_t* F;

// use CMP128 on any combination of pointers to 128-bit ints, i.e.

CMP128(A, B);
CMP128(&C[0], &D[0]);
CMP128(&E, F);

// and so on

допустим, я принимаю ограничение, согласно которому если вы передадите два перекрывающихся указателя, вы получите неопределенный результат.

Я пробовал что-то вроде этого (представьте, что эти макросы правильно отформатированы с обратной косой чертой -экранированные символы новой строки в конце каждой строки)

#define CMP128(x, y) ({
  uint64_t* a = (void*)x;
    uint64_t* b = (void*)y;

  // compare a[0] with b[0], a[1] with b[1]
})

, но когда я разыменовываю a в макросе (a [0]

. подумал, что вы должны использовать объединения, чтобы правильно ссылаться на одно место в памяти двумя разными способами, поэтому затем я попробовал что-то вроде

#define CMP128(x, y) ({
    union {
        typeof(x) a;
        typeof(y) b;
        uint64_t* c;
    }   d = { .a = (x) }
        , e = { .b = (y) };

    // compare d.c[0] with e.c[0], etc
})

За исключением того, что я получаю точно такие же ошибки от компилятора, касающиеся правил строгого сглаживания.

Итак: есть ли способ сделать это, не нарушая строгого псевдонима, кроме фактического КОПИРОВАНИЯ памяти?

( may_alias не считается, это просто позволяет вам чтобы обойти правила строгого псевдонима)

РЕДАКТИРОВАТЬ: для этого используйте memcmp. Я увлекся правилами псевдонима и не подумал об этом.

7
задан Vilhelm Gray 14 October 2016 в 13:32
поделиться