Wpis z mikrobloga

@walokid: to już zależy od architektury i czy zależy Ci na miejscu (np. na małych micro gdzie structure masz później w jakiejś dużej liście) czy na czasie dostępu.

Też przydatne jeśli potrzebujesz strukture załadować bezpośrednio z pliku, np. gdy chcesz sobie nagłówek pliku BMP załadować bezpośrednio od pamięci itp.
  • Odpowiedz
@cordianss: kompilator jest zobligowany do przestrzegania zasad działania CPU na który kompiluje. Na niektórych architekturach dostęp do niewyrównanych danych nie jest w ogóle dozwolony, na innych jest dozwolony ale kosztuje więcej.
  • Odpowiedz
  • 0
@Krolik: a to nie jest tak że C/Cpp jest zobligowany do tego że można wykonywać na nim operacje na bajtach(jakkolwiek są zdefiniowane) a typy które podałem są bajtami/wielokrotnościami bajtów więc wskaźniki do nich powinny być validne niezależnie od architektury?
  • Odpowiedz
@walokid: nie jest tak, jedynie wskaźniki do bajtów są prawidłowe niezależnie od wyrównania ale konwersja wskaźnika na inny typ jeśli wskaźnik ma złe wyrównanie to też UB i standard mówi o tym wprost. Nie możesz rzutować wskaźnika na bajt na niewyrównany wskaźnik na int.

http://www.catb.org/esr/structure-packing/

Jak masz niewyrównane dane i chcesz je np. odczytać jako int to najpierw musisz zrobić memcpy pod adres prawidłowo wyrównany do rozmiaru int i dopiero potem
  • Odpowiedz
@Krolik: Padding jest implementation defined, co oznacza tyle, że kompilator stara się wyrównywać wszystko tak, żeby pasowało do architektury. Na innych architekturach/kompilatorach odpowiedź na to pytanie z wpisu może być inna.

Jak masz niewyrównane dane i chcesz je np. odczytać jako int to najpierw musisz zrobić memcpy pod adres prawidłowo wyrównany do rozmiaru int i dopiero potem możesz robić odczyt.

Mówisz o strict aliasingu, czy o alignmancie?
Tutaj mam niewyrównanego inta
  • Odpowiedz
@cordianss: ale wiesz że UB nie oznacza że nie będzie działał? Poza tym w tym programie przecież nie ma nigdzie wskaźnika do niewyrównanego pola. Nie zrozumiałeś - nie jest problemem posiadanie niewyrównanego pola i jego bezpośredni odczyt /zapis bo kompilator widzi wtedy jakie jest wyrównanie tylko utworzenie wskaźnika do niego i posługiwanie się potem samym wskaźnikiem. Standard C zakłada że wskaźniki są wyrównane.
  • Odpowiedz
@Krolik:

ale wiesz że UB nie oznacza że nie będzie działał?

Wywołanie constexpr nie może mieć UB.

Nie zrozumiałeś - nie jest problemem posiadanie niewyrównanego pola i jego bezpośredni odczyt /zapis bo kompilator widzi wtedy jakie jest wyrównanie tylko utworzenie wskaźnika do niego i posługiwanie się potem samym wskaźnikiem. Standard C zakłada że wskaźniki są wyrównane.

Możesz pokazać jakiś mały snippet?
  • Odpowiedz
@cordianss:

Na podstawie Twojego przykładu kodu, jakbyś napisał tak:

Foo f;
int* foo = &f.x2; // UB, bo nie jest dozwolone utworzenie wskaźnika na int, który nie jest wyrównany do rozmiaru int
  • Odpowiedz
@cordianss

To że działa nie oznacza że jest poprawne

Standard C:

A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. *If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined.*


A tu masz bardziej łopatologicznie wytłumaczone, dlaczego tak nie wolno: https://stackoverflow.com/questions/70980038/how-to-properly-access-packed-struct-members

I jeszcze taka informacje znalazłem:

In GCC (C or C++), the compiler handles
  • Odpowiedz