Багато плутанини щодо вказівників на С походить від дуже поганого вибору, який спочатку був зроблений щодо стилю кодування, підтвердженого дуже поганим вибором у синтаксисі мови.
int *x = NULL;правильний C, але це дуже оманливе, я б навіть сказав безглузде, і це заважає розумінню мови багатьом новачкам. Це змушує думати, що пізніше ми могли б зробити це, *x = NULL;що, звичайно, неможливо. Розумієте, тип змінної не є int, а ім’я змінної - ні *x, а *також декларація не відіграє жодної функціональної ролі у співпраці з =. Це суто декларативно. Отже, набагато більше сенсу є ось що:
int* x = NULL;що також є правильним C, хоча воно не відповідає оригінальному стилю кодування K&R. Це чітко дає зрозуміти, що тип є int*, а змінна вказівника є x, тому навіть для непосвячених стає очевидним, що значення NULLзберігається x, яке є вказівником на int.
Крім того, це полегшує виведення правила: коли зірка знаходиться далеко від імені змінної, тоді це декларація, тоді як зірка, прикріплена до імені, є розмежуванням покажчика.
Отже, тепер стає набагато зрозумілішим, що далі ми можемо або робити, x = NULL;або *x = 2;іншими словами, новачкові легше бачити, як це variable = expressionведе до pointer-type variable = pointer-expressionта dereferenced-pointer-variable = expression. (Для ініційованих, під виразом 'я маю на увазі' rvalue '.)
Невдалий вибір у синтаксисі мови полягає в тому, що при оголошенні локальних змінних ви можете сказати, int i, *p;яке оголошує ціле число та вказівник на ціле число, тому це змушує вважати, що *це корисна частина імені. Але це не так, і цей синтаксис - це просто химерний особливий випадок, доданий для зручності, і, на мій погляд, він ніколи не мав би існувати, оскільки він анулює правило, яке я запропонував вище. Наскільки мені відомо, ніде більше в мові цей синтаксис не має значення, але навіть якщо він є, це вказує на розбіжність у способі визначення типів покажчиків у C. Всюди, в оголошеннях з однією змінною, у списках параметрів, у членах struct та ін. Ви можете оголосити свої вказівники type* pointer-variableзамість type *pointer-variable; це цілком законно і має більше сенсу.
int *x = whatever;робить, і тим, щоint *x; *x = whatever;робить.int *x = whatever;насправді поводиться якint *x; x = whatever;ні*x = whatever;.