walokid
#cpp #programowanie #informatyka #programista15k

Zagadka nr 8. Jakiego outputu programu się spodziewasz?

Jakiego outputu się spodziewasz

  • > 38.9% (21)
  • < 14.8% (8)
  • == 46.3% (25)

54 głosy

  • Najlepsze
  • Wszystkie komentarze
c.....s
@Kolczaneiro: Odpowiedź zależy od tego jak kompilator to implementuje.
MamCieNaHita
@walokid: fajny miałeś padding
walokid
walokid Autor
1
@walokid: na obrrazku jest błąd w coucie drugiego warunku ale to nic nie zmienia. Wiadomo że chodzi o <
sorek
sorek
1
@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.
Krolik
Krolik
@cordianss

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

Standard C:
walokid
walokid Autor
0
@walokid: Poprawna odpowiedź

sorek
sorek
0
@walokid: dlatego #pragma pack(1) to podstawa oraz umiejętne ogarnianie paddingu.
walokid
walokid Autor
0
#pragma pack(1)


@sorek: nooo chyba nie koniecznie ( spada wydajność przy dostępie do pamięci). Najlepiej to chyba ręcznie ustawiać/pakować
Kolczaneiro
@walokid a odpowiedź przypadkiem nie zależy od systemu na którym uruchomimy program?
Krolik
Krolik
@walokid: tylko że wtedy wzięcie wskaźnika do pola takiej struktury to UB, tak mówi standard.
Krolik
Krolik
@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.
walokid
walokid Autor
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?
Krolik
Krolik
@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
c.....s
@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 i nie
Krolik
Krolik
@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.
c.....s
@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?
Krolik
Krolik
@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
c.....s