Ujemna wartość pamięci (printf %d) - dlaczego?

0

Cześć, jestem nowy.
Bardzo chciałbym nauczyć się języka C.
Dużo rzeczy ogarniam samemu, ale pewnych rzeczy kompletnie nie rozumiem :/

Np: dlaczego mój program często zwraca ujemne adresy pamięci?

#include <stdio.h>

int main(int argc, char *argv[])
{
    int i = 10;
    int *p = &i;

    printf("%d\n", &i);
    printf("%d\n", p);

	return 0;
}

run program:
-441736348
-441736348

Średnio raz na trzy uruchomienia wynik jest ujemny. Jak to możliwe, żeby pamięć
była tak adresowana? Co jest nie tak?

Pozdrawiam
Marcin

10

Prawdopodobnie masz 64-bitową maszynę, więc 64-bitowy adres wskaźnika zostaje zrzutowany na 32-bitową liczbę wymaganą przez formatter %d, "przekręcając" (ang. integer overflow) licznik w trakcie.

Do wyświetlania wskaźników powinieneś wykorzystać formatter %p:

printf("%p\n", &i);
printf("%p\n", p);

Średnio raz na trzy uruchomienia wynik jest ujemny

Btw, sam fakt, że otrzymujesz różne wskaźniki wynika między innymi z techniki https://en.wikipedia.org/wiki/Address_space_layout_randomization, mającej na celu ochronę programami przed atakami na ich pamięć; nie jest to powiązane z oryginalnym problemem, ale pracując ze wskaźnikami warto pamiętać, że coś takiego istnieje :-)

1
Patryk27 napisał(a):

Prawdopodobnie masz 64-bitową maszynę, więc 64-bitowy adres wskaźnika zostaje zrzutowany na 32-bitową liczbę wymaganą przez formatter %d, "przekręcając" (ang. integer overflow) licznik w trakcie.

Tak mam 64 bitowy os. Kurcze o tym nigdy bym nie pomyślał.

Do wyświetlania wskaźników powinieneś wykorzystać formatter %p:

Pomogło, dodałem tylko rzutowanie na void, tak jak pisało w manualu
(przy okazji kompilator przestał się obruszać).

#include <stdio.h>

int main(int argc, char *argv[])
{
    int i = 10;
    int *p = &i;

    printf("%p\n", (void *) &i);
    printf("%p\n", (void *) p);

	return 0;
}

Btw, sam fakt, że otrzymujesz różne wskaźniki wynika między innymi z techniki https://en.wikipedia.org/wiki/Address_space_layout_randomization, mającej na celu ochronę programami przed atakami na ich pamięć; nie jest to powiązane z oryginalnym problemem, ale pracując ze wskaźnikami warto pamiętać, że coś takiego istnieje :-)

Dziękuję!

6

Bitowość systemu nie ma tu nic do rzeczy: https://godbolt.org/z/oTMj48
Na 32 bitach wartość też można uzyskać wartość ujemną.
Wszystko zależy od tego, gdzie/kompilator, system umieści stos; i w związku z tym jaka będzie wartość 32 bitu adresu tej zmiennej, który potem będzie pełnił rolę znaku.

0
MarekR22 napisał(a):

Bitowość systemu nie ma tu nic do rzeczy: https://godbolt.org/z/oTMj48

Na 32 bitach wartość też można uzyskać wartość ujemną.
Wszystko zależy od tego, gdzie/kompilator, system umieści stos; i w związku z tym jaka będzie wartość 32 bitu adresu tej zmiennej, który potem będzie pełnił rolę znaku.

Fajna ta stronka. Dzięki za info i dobry przykład - od razu mi się rozjaśniło :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1