Предположим, у меня есть образец исходного файла 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. Я увлекся правилами псевдонима и не подумал об этом.