Załóżmy Mam plik źródłowy próbkę, test.c, której mam kompilacji tak:C przezwyciężaniu ograniczeń aliasing (?) Związki
$ gcc -03 -Wall
test. c wyglądać tak ..
/// 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
niech też powiedzieć, że akceptują ograniczenia, że jeśli przejdzie w dwóch nakładających się wskaźniki, masz niezdefiniowanej re Sults.
Próbowałem coś takiego (wyobraź sobie te makra są prawidłowo sformatowany z backslash-uciekł nowej linii na końcu każdej linii)
#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]
})
ale kiedy dereference A w makro (A [ 0] < b [0]) Otrzymuję "dereferencje łamie zasady ścisłego aliasingu" z gcc
Myślałem, że powinniście używać związków, aby właściwie odnosić się do jednego miejsca w pamięci na dwa różne sposoby, więc następnie próbowałem coś takiego jak
#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
})
Tyle że mam te same błędy z kompilatora o zasadach ścisłego-aliasingu.
A więc: czy jest jakiś sposób na zrobienie tego bez łamania ścisłego aliasingu, bez tak naprawdę KOPIOWANIE pamięci?
(may_alias Ilość robi, po prostu pozwala na ominięcie zasad ścisłego-aliasing)
EDIT: Redakcyjne memcmp to zrobić. Złapałem zasady dotyczące aliasingu i nie pomyślałem o tym.
Aby używać związków w sposób zgodny ze standardami, możesz czytać tylko od członka, do którego ostatnio pisałeś. –
@Kerrek: not true - C99 umożliwia karanie za pomocą związków, przypis przypisany temu wyraźnie został dodany za pomocą TC3; jednak kod Todda wciąż jest niepoprawny ... – Christoph
@Christoph: C1x jest jeszcze lepszy, poprawiono dodatek J (UB), aby umożliwić odczytanie bajtów odpowiadających ostatniemu zapisanemu elementowi (co oczywiście było celem w C99, ale najwyraźniej załącznik J został przeoczony wtedy). – ninjalj