Supongamos que tengo un archivo de origen, test.c, que soy compilar este modo:C superar las restricciones de aliasing (? Sindicatos)
$ gcc -Wall -03
prueba. c ve algo como esto ..
/// 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
Digamos también acepto la restricción de que si se pasa en dos punteros que se solapan, se obtiene re indefinido sults.
He intentado algo como esto (imaginar estas macros tienen el formato correcto con saltos de línea escapados al final de cada línea)
#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]
})
pero cuando eliminar la referencia a en la macro (un [ 0] < b [0]) me sale "rompe eliminación de referencias a normas estrictas-aliasing" errores de gcc
había pensado que se suponía que utilizar uniones haga referencia correctamente a un solo lugar en la memoria de dos maneras diferentes, por lo A continuación probé algo como
#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
})
Excepto que tengo exactamente los mismos errores del compilador acerca de las reglas estrictas-aliasing.
Entonces, ¿hay alguna forma de hacer esto sin romper el alias estricto, menos COPIA la memoria?
(may_alias recuento no funciona, sólo se le permite eludir las estrictas reglas-aliasing)
EDIT: memcmp uso para hacer esto. Me quedé atrapado en las reglas de aliasing y no pensé en eso.
Para utilizar las uniones de forma estándar, solo puede leer el miembro al que escribió por última vez. –
@Kerrek: no es cierto: C99 permite escribir mensajes a través de uniones, una nota al pie que menciona explícitamente que se agregó con TC3; sin embargo, el código de Todd sigue siendo incorrecto ... – Christoph
@Christoph: C1x es aún mejor, el apéndice J (UB) es fijo, para permitir la lectura de los bytes correspondientes al último miembro escrito (que obviamente fue el propósito en C99, pero aparentemente el apéndice J fue pasado por alto). – ninjalj