Strukturované datové typy
Proměnné typu struktura (struct) jsou v jazyce C v paměti uloženy jednoduše jako její prvky za sebou, tzn. adresa struktury je stejná jako adresa jejího prvního prvku. Např. struct { long a; short b; } s;
je uložena jako 6 bytů - 4 byty pro a
, 2 pro b
, přes proměnnou s
se v assembleru dostaneme k prvnímu prvku s.a.
Při práci se strukturami je potřeba brát v potaz, že pro větší efektivnost dochází ješte k tzv. zarovnání velikosti struktury (padding) na vhodný násobek 4 nebo 8. To znamená, že i když výše uvedená struktura potřebuje k uchování dat pouze 6 bytů, ve skutečnosti zabere v paměti 8 bytů. Ověřte si to vhodným použitím operátoru sizeof
.
Vedle zarovnání velikosti objektů je potřeba dbát i na zarovnání jednotlivých členů struktury. Hodnoty velikosti jeden byte jsou zarovnávany na 1B, dvoubytové hodnoty na 2B, čtyřbytové hodnoty na 4B, atd. V praxi to znamená, že jednotlivé členy daného typu začínají vždy na násobku svého zarovnání, např. hodnoty typu int
jsou ve struktuře uložené vždy na pozici, která je násobkem čtyř. Toto chování je nutné mít na paměti při návrhu datových struktur, protože může vést k nevhodné spotřebě paměti. Pozici, na které je daný člen uložen, je možné v jazyce C zjistit pomocí makra offsetof(struktura, clen)
ze stddef.h
.
#include <stdio.h> #include <stddef.h> struct foo { char a; short b; int c; }; struct foo bar; int main() { bar.a = 0; bar.b = 100; bar.c = 200; printf("%i\n", offsetof(struct foo, b)); _asm { mov ebx, offset bar; mov byte ptr [ebx], 'd'; // ulozi do bar.a = 'd' mov cx, [ebx + 2]; // ulozi do cx hodnotu bar.b mov eax, [ebx + 4]; // ulozi do eax hodnotu bar.c mov dword ptr [ebx + 3], eax // !!! provede nesmyslnou operaci } return 0; }
Úkol
- Zjistěte pozice jednotlivých členů ve struktuře
struct foo
. Prohozením členů ověřte, že se překladač chová, jak je výše popsáno. Ověřte, že pořadí členů ovlivňuje velikost struktury. - Naprogramujte databázi osob.
- Navrhněte vhodnou strukturu, která pojme následující informace -- jméno (char *), datum narození (zvolte vhodnou reprezentaci), výška (unsigned char), váha (unsigned short).
- Naprogramujte funkci
db_add
s parametry jméno, datum narození, výška a váha -- která přidá položku do databáze. - Naprogramujte funkci
db_print
, která vypíše obsah databáze. - Naprogramujte funkci
db_avg_height
, která vrací průměrnou výšku osob v databázi. - Naprogramujte funkci
db_avg_weight
, která vrací průměrnou váhu osob v databázi.