• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Czego użyć zamiast struct aby sizeof zwracał odpowiednią wartość?

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
653 wizyt
pytanie zadane 6 czerwca 2023 w C i C++ przez Daaa22 Dyskutant (8,250 p.)
#include <stdio.h>

struct x
{
    int x;
    char c;
};

int main()
{
    printf("%d", sizeof(struct x)); //pokazuje 2*sizeof(int) zamiast sizeof(int)+sizeof(char)

    return 0;
}

Union pokaże sizeof(int), da się jakoś zaalokować pamięć tak żeby nie zabierała niepotrzebnego miejsca?

2 odpowiedzi

+3 głosów
odpowiedź 6 czerwca 2023 przez adrian17 Mentor (350,860 p.)

Nie, wszystko się zgadza. Rozmiar struktury nie jest równy po prostu sumie rozmiarów elementów, przez konieczność wyrównania:

https://en.cppreference.com/w/c/language/object#Alignment

Ma nawet dokładnie Twój kod jako przykład:

// objects of struct X must be allocated at 4-byte boundaries
// because X.n must be allocated at 4-byte boundaries
// because int's alignment requirement is (usually) 4
struct X {
    int n;  // size: 4, alignment: 4
    char c; // size: 1, alignment: 1
    // three bytes padding
}; // size: 8, alignment: 4

 

+1 głos
odpowiedź 6 czerwca 2023 przez Gynvael Coldwind Nałogowiec (30,110 p.)

Sizeof pokazuje dobrą wartość – po prostu nie bierzesz pod uwagę wyrównania, które jest w struct.

Generalnie każde pole w struct/class będzie miało "naturalne" wyrównanie do adresu podzielnego przez (zazwyczaj) wielkość danego pola. Do tego sam struct też będzie wyrównany jeśli chodzi o wielkość, tak żeby (w razie alokacji tablicy instancji structów) kolejny struct też był na odpowiednio wyrównanym adresie. Więc ten Twój struct ma de facto 3 elementy:

  1. int x (4 bajty)
  2. char c (1 bajt)
  3. + wyrównanie (3 bajty)

Dzięki temu struct ma 8 bajtów, więc jeśli zaalokujesz tablicę dwóch, to pierwsze pole każdego elementu tablicy ma zagwarantowane, że będzie na adresie podzielnym przez 4 (tak jak wymaga tego "naturalne" wyrównanie intów).

Jeśli się zastanawiasz po co te wyrównania, to generalnie chodzi o dostęp do pamięci. Dostęp do elementów na "naturalnie" wyrównanych adresach jest po prostu szybszy (co wynika z tego, że procesor może pominąć pewne checki związane z granicznymi przypadkami co do cache lines / stron pamięci).

W każdym razie jeśli potrzebujesz z jakiegoś powodu struct który ma dokładnie 5 bajtów (np. odczyt/zapis do pliku, albo wysyłka pakietów sieciowych), to rzuć okiem na:

  • #pragma pack
  • __attribute__((packed))

Np.

// zachowanie ustawień i wyłączenie wyrównywania
#pragma pack(push,1)

struct asdf {
  int x;
  char c;
};

// przywrócenie poprzedniego zachowanego ustawienia
#pragma pack(pop)

// sizeof tego structa zwróci 5

 

komentarz 7 czerwca 2023 przez Gynvael Coldwind Nałogowiec (30,110 p.)

ETA: ↑↑↑ wcześniej tu był jeszcze jeden komentarz, serio!1one

Akurat liczbę oddzielnych dostępów do pamięci da się bardzo łatwo przewidzieć widząc sam adres i znając wielkość zmiennej + rozumiejąc model pamięci. Np. rozważania dla inta na x86:

  • 0x1004 - jeden dostęp do pamięci.
  • 0x1005 - dwa dostępy do pamięci w obrębie tego samego cache line (2x wolniejsze).
  • 0x103f - dwa dostępy do pamięci na dwóch różnych cache line (potencjalnie sporo wolniejsze).
  • 0x1fff - dwa dostępy do pamięci na dwóch różnych stronach pamięci (dużo dużo wolniejsze).

Dla zainteresowanych sekcja 4 w tym papierku :)
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/42189.pdf

Podobne pytania

–1 głos
0 odpowiedzi 676 wizyt
pytanie zadane 9 czerwca 2018 w C i C++ przez MsMaciek123 Pasjonat (24,760 p.)
0 głosów
1 odpowiedź 440 wizyt
pytanie zadane 19 kwietnia 2023 w C i C++ przez Daaa22 Dyskutant (8,250 p.)
0 głosów
1 odpowiedź 759 wizyt

93,173 zapytań

142,184 odpowiedzi

321,968 komentarzy

62,502 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 1157p. - dia-Chann
  2. 1139p. - Łukasz Piwowar
  3. 1131p. - CC PL
  4. 1126p. - Łukasz Eckert
  5. 1118p. - Tomasz Bielak
  6. 1104p. - Michal Drewniak
  7. 1083p. - Marcin Putra
  8. 1078p. - rucin93
  9. 1071p. - rafalszastok
  10. 1054p. - Adrian Wieprzkowicz
  11. 1047p. - Piotr Aleksandrowicz
  12. 1037p. - Michał Telesz
  13. 1017p. - Mikbac
  14. 1005p. - ssynowiec
  15. 992p. - Dominik Łempicki (kapitan)
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...