Wskaźniki - trochę z teorii

0

Witam

jaka będzie różnica pomiędzy poniższymi definicjami:
char napis[80] = "Przykładowe zdanie";
char napis[] = "Przykładowe zdanie";
char *napis = "Przykładowe zdanie";

0

Witam
dzięki!
mam jeszcze pytanie odnośnie takiej sytuacji:

int tablica [2][2];
int *wsk;

dlaczego takie odwołanie zadziała:

wsk = tablica[1];

a takie nie:

wsk = tablica[1][1];
1

Bo robiąc

tablica[1][1]; 

wydobędziesz konkretny element czyli inta, a nie wskaźnik na inta

4

Główną różnicą jest co, jak i gdzie jest alokowane.

W pierwszych dwóch przypadkach, alokujesz na stosie N znaków (tablice). W 3 przypadku tego nie robisz (tj. alokujesz tylko wskaźnik na char).

#include <stdio.h>
#include <string.h>

#define PRINT_SIZE(name, x) printf("%s size: %d\n", (name), sizeof(x))

int main() {
    char napis1[80] = "Przykladowe zdanie.";
    char napis2[]   = "Przykladowe zdanie.";
    char* napis3    = "Przykladowe zdanie.";

    PRINT_SIZE("napis1", napis1);
    PRINT_SIZE("napis2", napis2);
    PRINT_SIZE("napis3", napis3);

    return 0;
}
napis1 size: 80
napis2 size: 20
napis3 size: 4

Następną różnicą jest to co dostajesz, tj. w 2 pierwszych przypadkach masz tablice do dowolnego użytku praktycznie, do której wrzucany jest ten ciąg. W 3 tylko ustawiasz wskaźnik na niego. Jakie to ma znaczenie? Ano takie, że wskaźnik ten wskazuje na pamięć tylko do odczytu. Spójrzmy na adresy (Windows, MinGW).

#include <stdio.h>
#include <string.h>

#define PRINT_ADDR(name, x) printf("%s addr: %p\n", (name), (x))

int main() {
    char napis1[80] = "Przykladowe zdanie.";
    char napis2[]   = "Przykladowe zdanie.";
    char* napis3    = "Przykladowe zdanie.";

    PRINT_ADDR("napis1", napis1);
    PRINT_ADDR("napis2", napis2);
    PRINT_ADDR("napis3", napis3);

    getchar();

    return 0;
}
napis1 addr: 0028FEEC
napis2 addr: 0028FED8
napis3 addr: 0040A064

Teraz zobaczmy pod debuggerem, co to za adresy:

81e2abb4bf.png

Jak widzisz 2 pierwsze są ulokowane w miejscu zwanym Stack of main thread (stos głównego wątku), który ma poziom dostępu RW (Read Write), czyli możemy zarówno czytać jak i pisać (tj. modyfikować elementy tablicy).
W 3 przypadku napis ulokowany jest w sekcji .rdata, który ma poziom dostępu R (Read) czyli pozwala tylko na czytanie.

Z powyższego też wynika, że pisanie linijki char* x = "jakiś ciąg znaków" nie jest zbytnio dobrym zwyczajem, a powinno się raczej robić const char* x = "jakiś ciąg znaków".

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