Wiele nieporozumień związanych ze wskaźnikami C wynika z bardzo złego wyboru, którego pierwotnie dokonano w odniesieniu do stylu kodowania, potwierdzonego bardzo złym, niewielkim wyborem w składni języka.
int *x = NULL;
ma rację C, ale jest bardzo mylące, powiedziałbym nawet, że bezsensowne i utrudniało zrozumienie języka wielu nowicjuszom. Pozwala to pomyśleć, że później moglibyśmy to zrobić, *x = NULL;
co jest oczywiście niemożliwe. Widzisz, typ zmiennej nie jest int
, a nazwa zmiennej nie *x
, ani *
w deklaracji nie odgrywa żadnej funkcjonalnej roli we współpracy z =
. Jest czysto deklaratywna. Więc o wiele bardziej sensowne jest to:
int* x = NULL;
co jest również poprawne C, choć nie jest zgodne z oryginalnym stylem kodowania K&R. To doskonale wyjaśnia, że typ jest int*
, a zmienna wskaźnikowa x
tak, więc nawet dla niewtajemniczonych staje się jasne, że wartość NULL
jest przechowywana w x
, czyli wskaźniku do int
.
Ponadto ułatwia wyprowadzenie reguły: gdy gwiazda znajduje się z dala od nazwy zmiennej, jest to deklaracja, podczas gdy gwiazda dołączona do nazwy jest dereferencją wskaźnika.
Tak więc teraz staje się o wiele bardziej zrozumiałe, że dalej możemy to zrobić x = NULL;
lub *x = 2;
innymi słowy, nowicjuszowi łatwiej jest zobaczyć, jak variable = expression
prowadzi do pointer-type variable = pointer-expression
i dereferenced-pointer-variable = expression
. (Dla wtajemniczonych przez „wyrażenie” mam na myśli „wartość r”.)
Niefortunnym wyborem w składni języka jest to, że podczas deklarowania zmiennych lokalnych można powiedzieć, int i, *p;
która deklaruje liczbę całkowitą i wskaźnik do liczby całkowitej, więc prowadzi to do przekonania, że *
jest to użyteczna część nazwy. Ale tak nie jest, a ta składnia to po prostu dziwaczny przypadek specjalny, dodany dla wygody i moim zdaniem nigdy nie powinien istnieć, ponieważ unieważnia regułę, którą zaproponowałem powyżej. O ile mi wiadomo, nigdzie indziej w języku ta składnia nie ma znaczenia, ale nawet jeśli tak jest, wskazuje ona na rozbieżność w sposobie definiowania typów wskaźników w C. Wszędzie indziej, w deklaracjach pojedynczych zmiennych, na listach parametrów, w elementach strukturalnych itp. możesz zadeklarować swoje wskaźniki jako type* pointer-variable
zamiast type *pointer-variable
; jest to całkowicie legalne i ma więcej sensu.
int *x = whatever;
robi, a tym, coint *x; *x = whatever;
robi.int *x = whatever;
faktycznie zachowuje się jakint *x; x = whatever;
nie*x = whatever;
.