Правильний спосіб оголошення змінних покажчика в C / C ++ [закрито]


91

Я помітив, що деякі люди використовують такі позначення для оголошення змінних покажчика.

(a) char* p;

замість

(b) char *p;

Я використовую (b). Що є раціональним за позначенням (а)? Позначення (b) для мене має більший сенс, оскільки вказівник символу сам по собі не є типом. Натомість тип - символ, а змінна може бути вказівником на символ.

char* c;

Здається, існує тип char *, а змінна c є цим типом. Але насправді тип - char, а * c (місце пам'яті, вказане c) - це тип (char). Якщо ви оголосите кілька змінних одночасно, ця відмінність стає очевидною.

char* c, *d;

Це виглядає дивним. І c, і d - однакові вказівники, що вказують на символ. У цьому, оскільки наступний виглядає більш природно.

char *c, *d;

Дякую.


7
Що ви маєте на увазі, що покажчик char не є типом? Ви хочете сказати, що вказівник не є типом?
Бенджамін Ліндлі

1
Я вважаю, що це питання переваг, якщо ви не переглядаєте певний посібник зі стилю (тобто ваша компанія може мати певний стандарт кодування, якого ви повинні дотримуватися). Я схильний змішувати це між вибором b та десь посередині. Іноді я не відчуваю себе char *tналежним чином, тому я можу робити це char * t;замість цього. Однак я також часто бачив char* t;це.
RageD

1
Крім того, ваші міркування "тип char і * c (розташування пам'яті, на яке вказує c) має такий тип (char)" , здається, вказують на те, що декларується символ, а насправді його немає. Якщо до нього ставитись як до такого, як це іноді роблять новачки, це, безсумнівно, призведе до порушень доступу до пам'яті.
Бенджамін Ліндлі,

1
Обидва вони все ще достатньо описові, (b) показує * p типу charі (a) показує p is apointer to a char
A Person

1
Маючи понад десятирічний досвід роботи в галузі, сьогодні це було вперше, і лише при читанні статей від інших спеціалістів галузі. Очевидно, отже, я ніколи не мав таких релігійних розмов про них, як у мене було із вкладками v пробіли, коментарями def або dec, або будь-якою іншою темою "добре, щоб не було нічого важливішого для сперечань" . З огляду на мою перспективу, я віддав перевагу, так пізно в грі своєї кар’єри, частіше ходити з "char * p". Так, простір до, простір після. В основному, як я вважаю, це зменшує помилки, оскільки робить вказівність більш очевидною.
Kit10,

Відповіді:


102

Бьярн Страуструп сказав:

Вибір між "int * p;" та "int * p;" йдеться не про правильне і неправильне, а про стиль та акценти. С наголошені вирази; декларації часто вважалися не більше ніж необхідним злом. З іншого боку, C ++ робить сильний акцент на типах.

"Типовий програміст на С" пише "int * p;" і пояснює це "* p is what is the int" підкреслюючи синтаксис, і може вказувати на граматику декларації C (і C ++), щоб аргументувати правильність стилю. Дійсно, * пов'язується з назвою p в граматиці.

"Типовий програміст на C ++" пише "int * p;" і пояснює це "p - це вказівник на тип int", що підкреслює. Дійсно, тип p - це int *. Я чітко віддаю перевагу такому наголосу і вважаю його важливим для використання більш досконалих частин C ++.

Джерело: http://www.stroustrup.com/bs_faq2.html#whitespace

Я б порекомендував останній стиль, оскільки в ситуації, коли ви оголошуєте кілька покажчиків в одному рядку (ваш 4-й приклад), зірочка зі змінною буде тим, до чого ви звикли.


34
Інші рекомендують ніколи не оголошувати кілька об'єктів в одній декларації. :-)
Бо Перссон,

5
Я наголошую на логіці синтаксису, отже, я віддаю перевагу:, що int *pозначає: коли pдереференціюється, я отримую int. Тоді ,має сенс декілька оголошень, розділених знаком: int *p, *q, r(коли pабо qдереференціюється, я отримую int, коли rпосилається, я отримую int). Крім того, синтаксис покажчика функції має сенс: int (*f)()(коли fвідбувається розмежування та викликається я отримую int). І це має сенс: int *p, (*f)().
Druesukker

2
Це допомогло мені зрозуміти, що обґрунтованість має інша сторона аргументу. Будучи, в основному, програмістом високого рівня, я наголошую на типі; і віддають перевагу int*. Для мене int *p, (*f)()це не має особливого сенсу, але я можу зрозуміти, як це було б для деяких людей у ​​деяких ситуаціях.
Ассимілатор

1
@Druesukker, на мою думку, ваше твердження має більше сенсу, ніж будь-яке з перерахованих.
Мунташир Акон

1
@Druesukker Але логіка не зовсім працює void*(і взагалі не працює для посилань на C ++).
jamesdlin

57

Я особисто вважаю за краще розміщувати їх *з іншими типами

char* p;  // p is a pointer to a char.

Люди будуть сперечатися, "але потім char* p, q;стає оманливим", на що я кажу, "так що не робіть цього".


Дуже хороший аргумент для char * p; вибір :) Я не проти жодного з них, поки не стане важко прочитати приклад, який ви показали, і в цьому випадку вони не повинні цього робити.
Ісус Рамос,

1
А коли ви хочете вивести значення? Ти робиш cout << *p;. То чому б не поставити зірку раніше p під час оголошення *p:? На мій погляд, це було б менш заплутаним.
user1170330

13
@ user1170330, оскільки в одному місці це частина визначення типу, а в іншому - оператор розвідки. Ніякого відношення. Якщо що, добре, що вони виглядають по-різному, оскільки різні речі повинні виглядати по-різному.
ikegami

32

Немає різниці, як писати. Але якщо ви хочете оголосити два або більше покажчиків в одному рядку, краще використовувати варіант (b), оскільки зрозуміло, що ви хочете. Подивіться нижче:

int *a;
int* b;      // All is OK. `a` is pointer to int ant `b` is pointer to int
char *c, *d; // We declare two pointers to char. And we clearly see it.
char* e, f;  // We declare pointer `e` and variable `f` of char type.
             // Maybe here it is mistake, maybe not. 
// Better way of course is use typedef:
typedef char* PCHAR;
PCHAR g, h;  // Now `g` and `h` both are pointers.
// If we used define construction for PCHAR we'd get into problem too.

5
typedefне кращий спосіб "звичайно". Деякі люди можуть це віддати перевагу, але це проблематично, якщо з вашим кодом працює кілька людей. Якби я не звик PCHAR, я міг написати щось на зразок того PCHAR *p;, що було б, char**а не тим, що я маю намір. Загалом, якщо ви хочете char**, вам доведеться написати PCHAR*або визначити новий тип, і тоді він просто починає дурити.
BlackJack

3
Якщо для роботи потрібен якийсь складний тип вказівника, такий як вказівник, дуже добре створити typedefs. У цьому випадку вони роблять код набагато простішим. З іншого боку, використання PCHAR є більш синтетичним прикладом, ніж повсякденна практика. Але це чітко робить те, що ви хочете. а потім це просто починає
дурити

Якщо ви написали PCHAR * p для визначення вказівника на char, було б очевидно, що ви не знаєте, що робите, і не читали тип def. Відповідь на його думку. Є ще одна перевага для typedef; в C - це прості способи зробити речі непрозорими. публічно визначте символ як VOID ptr, приватно тип def - це щось інше .... Я волів би час від часу коригувати typedef, а потім коригувати все в коді, коли ми змінюємо щось про один із типів ... але C ++ 11 вирішує багато з цього за допомогою авто
UpAndAdam

Для тих, хто просто намагається повернутися до іграшки з C ++ через п'ять років після коледжу, це одна з найкращих відповідей.
Panzercrisis

10

Компроміс є

char * p;

Використання K&R

char *p;

Це залежить від вас, якщо ви не дотримуєтеся стандарту кодування - у такому випадку ви повинні стежити за тим, що роблять усі інші.


4
Я важко дізнався, що char * x, y не означає, що y є char *. Тепер я бачу, чому K&R дотримується згаданого стилю.
Рахул Кадукар,

що таке K&R і чому має значення, що використовує одне джерело коду? Я використовую char* p;. це питання стилю, а не умовності чи правил. для мене має більше сенсу, що p має тип char*, тому, очевидно, * має бути з типом.
FalcoGer

@FalcoGer Я додав посилання для K&R. Не має значення, що використовує одне джерело коду. Ваша команда може вас дратувати, якщо ви не будете дотримуватися їхніх стандартів, оскільки ви змушуєте їх працювати більше, щоб зрозуміти ваш код. У ці дні я сподівався б, що команди все clang-formatодно використовують .
jnnnnn

2

Це все питання переваг, особисто для проектів, які я бачу char * Я схильний оголошувати кілька покажчиків на окремих рядках. Не існує реального "правильного" способу зробити це, і все зводиться до переваг. Одні кажуть, що легше читати (а), а інші кажуть, що (б) простіше оголосити більше змінних того самого типу в одному рядку.

Я вважаю, що (b) є більш поширеним, і в деяких випадках я бачив

char * a;

або щось подібне. Знову перевага. Незалежно від того, що вам комфортно, або для того, що використовує проект, над яким я працюю, я буду використовувати (якщо тільки я не напишу його сам, в цьому випадку використовую (а))

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.