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

Zadanie z C niskopoziomowego

+2 głosów
1,493 wizyt
pytanie zadane 6 września 2017 w C i C++ przez Madar Obywatel (1,560 p.)

Dobry wieczór,

uczę się do egzaminu poprawkowego i utknąłem na jednym z zadań z programowania niskopoziomowego o treści: 

"Ile bajtów pamięci potrzeba na przechowanie zmiennej typu T, zdefiniowanego poniżej, przy ułożeniu z dokładnością do: (a) 1 bajta, (b) 2 bajtów, (c) 4 bajtów1"

 

typedef struct {
 union {
 int x[2];
 float y[3];
 } u;
 double z;
} T;

 

Czy ktoś jest w temacie i pomógłby mi z rozwiązaniem i wyjaśni jak to policzyć?
Z góry dziękuję za pomoc :)

5 odpowiedzi

+2 głosów
odpowiedź 7 września 2017 przez madpl1239 Użytkownik (600 p.)
Unia to struktura, której pola nie występują jedno za drugim, tylko zaczynają się zawsze od tego samego miejsca.

Wielkość - długość w bajtach unii to wielkość najdłuższego elementu w tym agregacie:

a więc jesli mamy:

Union{

float size; // przypuśćmy, że 4 bajty

char chr; // standardowo 1 bajt

} U;

to sizeof(U) powinno dać nam 4 bajty.

Stąd jeśli w twoim zadaniu w tej uni najdłuższy bajtowo element to float y[3] bo ma 3x3 = 9 bajtów. Bo int x[2] ma tylko 4x2 = 8 bajtów. Przyjmujemy z twoich zapisków, że float to 3 bajty reprezentacji a typ int to 4 bajty reprezentacji.

a) Stąd, jeśli przyjmiemy, że ułożenie bajtów jest co do 1-go: czyli jeden obok drugiego to jesli unia ma 9 bajtów to zaraz za nią w strukturze jest typ double (5 bajtowa reprezentacja): 9+5 = 14

 

b) Teraz jesli ułożenie jest z dokładnością do 2 bajtów, czyli każda reprezentacja typu będzie w pamięci zaokrąglana do 2 bajtów rzeczywistej reprezentacji niewidocznej dla programisty to mamy: unia 3x3 = 9  i dodajemy 1 bajt ukryty, bo 10 to 5 dwójek czyli mamy reprezentację z dokładnością do 2 bajtów.  A typ double mający 5 bajtów też zostanie doposażony w jeden ukryty bajt bo 6 to trzy 2-bajtowe pola. Stąd 10 + 6 = 16   

 

c) W typ przypadku mamy dla uni:  3x3 = 9 ale 9 to dwa 4 bajtowe pola + 1 bajt następnej z czwórki bajtów (ma być reprezentacja z dokładnością do 4 bajtów) to unia będzie mieć 12 bajtów. Typ double to 5 bajtów ale w naszej maszynie najmniejsza jednostka może mieć 4 bajty więc na 5 bajtów musimy przydzielić  dwa czterobajtowe obszary stąd 8 bajtów i mamy w sumie: 12+8 = 20 :)))

 

Może tym wyjaśnieniem nieco rozjasniłem:))

 

Pozdrawiam
+1 głos
odpowiedź 6 września 2017 przez januszprogramowania Bywalec (2,840 p.)
W każdym z przypadków 20 bajtów - przy założeniu, że double jest 8 bajtowy a float i int 4.

Dlaczego:

Unia zajmuje tyle, ile jej największy element czyli w tym wypadku float y[3] a to jest 12 bajtów.

Do tego trzeba dodać 8 bajtów z double i mamy 20.

Wyrównanie do 1, 2, 4 bajtów nie zmienia wyników w tym szczególnym wypadku bo i 12 i 8 jest podzielne przez 1,2,4

 

No chyba, że się mylę :)
komentarz 6 września 2017 przez adrian17 Mentor (354,120 p.)
Na kilku różnych kompilatorach dostaję 24 :)
komentarz 6 września 2017 przez januszprogramowania Bywalec (2,840 p.)
W  ustawieniach projektu Visual Studio 2017 jest taka opcja: Właściwości konfiguracji->C/C++->Generowanie kodu->Wyrównanie członka struktury

Gdy tam ustawisz na 1,2 lub 4 wtedy sizeof da 20, jak 8 to 24.

Na Mac OS X też mi się nie udało uzyskać 20, ale nie grzebałem za bardzo
2
komentarz 6 września 2017 przez adrian17 Mentor (354,120 p.)
Nie będę w to wnikał - w każdym razie to pokazuje, że jeśli zadanie oczekuje jednoznaczną odpowiedź, to jest bez sensu :)
+1 głos
odpowiedź 6 września 2017 przez mbabane Szeryf (79,260 p.)
+1 głos
odpowiedź 7 września 2017 przez mokrowski Mędrzec (158,580 p.)
#include <stdio.h>

typedef struct __attribute__((packed)) {
    union {
        int x[2];
        float y[3];
    } u;
    double z;
} Tp;

typedef struct {
    union {
        int x[2];
        float y[3];
    } u;
    double z;
} T;

typedef struct __attribute__((packed, aligned(16))) {
    union {
        int x[2];
        float y[3];
    } u;
    double z;
} Ta16;

int main(void) {
    printf("sizeof(Tp) == %lu\n", sizeof(Tp));
    printf("sizeof(T) == %lu\n", sizeof(T));
    printf("sizeof(Ta16) == %lu\n", sizeof(Ta16));
    return 0;
}

Ścisła odpowiedź więc brzmi: "To zależy jakiego wyrównania wymaga dana platforma sprzętowa" :-). Domyślnie struktury bez specjalnych zabiegów (typ T), wyrównywane są do wartości zakresu pamięci specyficznej dla danej platformy systemowej. Atrybut packed, powoduje ich upakowanie ale kosztem (nieco) wolniejszego dostępu do składowych. Ostatni typ (Ta16) podałem jako przykład wymuszenia wyrównania do podanego zakresu.

Dodatkowo (szczególnie z tego powodu że to pytanie dotyczy programowania niskopoziomowego), warto zwrócić uwagę że int może mieć najmniej 2 bajty czyli 16 bitów.... bądź więcej :-) http://en.cppreference.com/w/c/language/arithmetic_types (ostatnia tabelka).

komentarz 7 września 2017 przez januszprogramowania Bywalec (2,840 p.)
W treści zadania podane jest dla jakich wyrównań
komentarz 7 września 2017 przez mokrowski Mędrzec (158,580 p.)
O? A kod nie pokazuje jak te wyrównania sprawdzić? :-)
komentarz 7 września 2017 przez januszprogramowania Bywalec (2,840 p.)

W  ustawieniach projektu Visual Studio 2017 jest taka opcja: Właściwości konfiguracji->C/C++->Generowanie kodu->Wyrównanie członka struktury 

Gdy tam ustawisz na 1,2 lub 4 wtedy sizeof da 20, jak 8 to 24. 

komentarz 7 września 2017 przez mokrowski Mędrzec (158,580 p.)

W  ustawieniach projektu Visual Studio 2017 jest taka opcja: Właściwości konfiguracji->C/C++->Generowanie kodu->Wyrównanie członka struktury  

Gdy tam ustawisz na 1,2 lub 4 wtedy sizeof da 20, jak 8 to 24. 

Stanowczo nie tędy droga. Przeczytaj (uważnie) dokumentację którą podałem wyżej.

komentarz 7 września 2017 przez januszprogramowania Bywalec (2,840 p.)
W oryginalnym pytaniu chodzi raczej o sposób wyliczenia ile podana struktura zajmie pamięci przy wyrównaniu do 1,2 i 4 bajtów. Zrobiłem pewne założenia co do wielkości typów podstawowych o których wspomniałem i na tej podstawie wyliczyłem 20. Obawiam się, że odpowiedź na egzaminie poprawkowym:"To zależy jakiego wyrównania wymaga dana platforma sprzętowa" nie będzie satysfakcjonująca. Oczywiście masz rację, że typy podstawowe mają różną wielkość w zależności od platformy i trzeba o tym wspomnieć.
+1 głos
odpowiedź 7 września 2017 przez NaviFox Dyskutant (8,950 p.)
"(c) 4 bajtów1" -- "1"

Kolego a czasami w zadaniu nie ma podanego odnośnika do wielkości typów danych dla tego zadania? I co to jest "ułożenie"? Numerowanie bitowe czy wyrównanie?

Podobne pytania

0 głosów
0 odpowiedzi 277 wizyt
pytanie zadane 23 czerwca 2019 w C i C++ przez wieczor9 Początkujący (370 p.)
0 głosów
1 odpowiedź 416 wizyt
0 głosów
0 odpowiedzi 272 wizyt

93,427 zapytań

142,421 odpowiedzi

322,649 komentarzy

62,787 pasjonatów

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

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...