@haracz: zanim wrócisz do swojej książki warto żebyś poświęcił trochę czasu żeby zrozumieć jak działają wskaźniki w C/C++.
Na poziomie CPU twoja tablica znaków typu char to tylko 40 bajtów w pamięci i nic więcej.
Zmienna stuffing
to dla kompilatora po prostu wskaźnik który zawiera adres tego obszaru pamięci. W bardzo starym C (K&R) nie było nawet operatora indeksowania, wszystko robiło się wskaźnikami.
Operacje na tablicach w języku wskaźników:
char a = abc[i];
abc[i] = 'b';
to
a = *(abc + i);
*(abc + i) = 'b';
Jak już pisałem pierwsze wersje jezyka C nie zawierały nawet operatora indeksowania. Jeżeli traktowalibyśmy wskaźniki jak czyste adresy w pamięci to musielibyśmy pamiętać żeby przesunąć wskaźnik o 4 pozycje żeby dobrać się do następnego elementu tablicy int'ów, a o 8 dla double'i. Jest to bardzo niewygodne, dlatego wymyślono że wskaźniki będą miały wsłasną arytmentykę. abc + 1
to nie adres abc plus jeden, ale następny element tablicy abc. Czyli:
int* p = 0x100;
p++;
printf("%p\n", p); // 0x104
double* d = 0x100;
d++;
printf("%p\n", d); // 0x108
Dla CPU 40 bajtów to 40 bajtów, czyli:
char stuffing[40];
równie dobrze można traktować jak tablicę 10 intów 4-bajtowych, lub 5 longów 8-bajtowych (x84_64).
for(i = 0; i <= 40; i+=4)
*(long*) &stuffing[i] = 0x80484bb;
puts(stuffing);
Powyższy kod traktuje stuffing jako tablicę 10 intów 4-bajtowych.
Ponieważ stuffing jest tablicą typu char, to &stuffing zwróci adres bajtu. Ale dla longów tutaj potrzebujemy adresu całych 4-bajtowych grup, stąd i+=4 a nie 1.
Jak już mamy adres takiej 4-bajtowej grupy to możemy ją traktować dowolnie np. jako long'a tak jak tu w przykładzie, ale moża też zrobić:
*(float *) &stuff ... = 3.14f;
Ale uwaga, nie wszystkie typy lubią być umiejszczane pod dowolnymi adresami. double i float (o ile dobrze pamiętam) trzeba umiejszczać pod adresami będącymi wielokrotonością 8 i 4.
Inaczej albo program działa wolno albo jest błąd (w zależności od CPU).
Kolejna sprawa to endianness, na x84 jak masz inta 0xaabbccdd to w pamięci bajty ułożone są odwrotnie a więc dd cc bb aa (od najmniejszego do najwiekszego adresu pamięci).
Jest już późno ale wydaje mi się że ta pętla powinna mieć warunke i < 40
a nie i <= 40
. Jeżeli chodzi o puts
to wygląda na to że będą się wypisywać smieci aż trafimy na pierwsze zero.