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";
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";
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];
Bo robiąc
tablica[1][1];
wydobędziesz konkretny element czyli inta, a nie wskaźnik na inta
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:
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"
.