Предположим, у меня есть исходный исходный файл 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
пусть также скажу, что я принимаю ограничение, что если вы передадите два наложенных указателя, вы получите результаты undefined.
Я пробовал что-то вроде этого (представьте, что эти макросы должным образом отформатированы с использованием строк с обратной косой чертой в конце каждой строки)
#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] < b [0]), я получаю ошибки "разыменования разрывов строгого сглаживания" из gcc
Я думал, что вы должны использовать союзы, чтобы правильно ссылаться на одно место в памяти двумя разными способами, поэтому я попробовал что-то вроде
#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 не учитывает, он просто позволяет обойти правила строгого сглаживания)
EDIT: для этого используйте memcmp. Я попался на правила псевдонимов и не думал об этом.