2009-12-10 7 views
15

Oczekuję, że oba następujące wektory mają taką samą reprezentację w RAM:C - Różnica między "char var []" i "char * var"?

char a_var[] = "XXX\x00"; 
char *p_var = "XXX"; 

Ale dziwne, wywołanie funkcji biblioteki typu f(char argument[]) crushs uruchomionej aplikacji jeśli zgłoszę go za pomocą f(p_var). Ale używanie f(a_var) jest OK!

Dlaczego?

Odpowiedz

26

Pierwsza tworzy tablicę znaków zawierającą ciąg. Zawartość tablicy można zmodyfikować. Drugi tworzy wskaźnik znaku, który wskazuje na literał ciągu. Literałów łańcuchowych nie można modyfikować.

+0

Jak wiem, w ANSI C wszystko można zmodyfikować – psihodelia

+15

Wiesz źle. Standard zabrania modyfikacji literałów łańcuchowych. –

+0

OK, dzięki! Teraz zapamiętam to na zawsze :) – psihodelia

1

W odgadywaniu funkcja f modyfikuje zawartość przekazywanego do niej łańcucha.

+0

tak, modyfikuje. ale dlaczego f (p_var) sprawia, że ​​crush i f (a_var) nie? – psihodelia

+1

ponieważ: char * p_var = "XXX"; Nie można modyfikować. –

0

Tablice mogą być traktowane (ogólnie) jako wskaźniki, ale nie oznacza to, że są zawsze wymienne. Jak powiedział drugi, twoje p_var wskazuje na dosłowne, coś statycznego, którego nie można zmienić. Może wskazywać na coś innego (np. P_var = & a_var [0]), ale nie można zmienić oryginalnej wartości określonej przez cudzysłowy ....

Podobny problem występuje, gdy definiuje się zmienną jako array w jednym pliku, a następnie extern - użyj go jako wskaźnika.

Pozdrowienia

1

Jak inni powiedział char *p_var = "XXX"; tworzy wskaźnik do łańcucha dosłownym, które nie mogą być zmieniane, więc implementacje kompilatora są wolne do ponownego użycia literałów, na przykład:

char *p_var = "XXX"; 
char *other = "XXX"; 

Kompilator może wybierz zoptymalizować to, przechowując "XXX" tylko raz w pamięci i wskazując na oba wskaźniki, modyfikując ich wartość może prowadzić do nieoczekiwanego zachowania, dlatego nie należy próbować modyfikować ich zawartości.