Яка різниця між const int *, const int * const і int const *?


1355

Я завжди безлад , як використовувати const int*, const int * constі int const *правильно. Чи існує набір правил, що визначають, що можна, а що не можна робити?

Я хочу знати всі дії та всі недоліки щодо завдань, переходу до функцій тощо.


175
Ви можете використовувати "Правило по годиннику / спіраль" для розшифровки більшості декларацій C і C ++.
Джеймс Макнелл

52
cdecl.org - це чудовий веб-сайт, який автоматично переводить декларації C для вас.
Дейв Галлахер

6
@Calmarius: почніть там, де є / має бути ім’я типу, рухайтеся праворуч, коли можете, вліво, коли потрібно . int *(*)(char const * const). Починають праворуч від дужки , *то ми повинні рухатися вліво: pointer. Поза дужками, ми можемо рухатися вправо: pointer to function of .... Тоді ми повинні рухатися зліва pointer to function of ... that returns pointer to int. Повторіть , щоб розгорнути параметр ( ...): pointer to function of (constant pointer to constant char) that returns pointer to int. Яка еквівалентна однорядкова декларація повинна бути легкою для читання мовою, як Pascal?
Марк К Коуан

1
@MarkKCowan У Паскалі це було б щось на кшталт function(x:^char):^int. Там типи функцій означають вказівник на функцію, тому не потрібно її вказувати, і Pascal не виконує правильність const. Його можна читати зліва направо.
Кальмарій

5
Перше, що ліворуч від "const" - це те, що є постійним. Якщо "const" - це річ, яка знаходиться найдаліше зліва, то перше, що праворуч від неї, - це те, що є постійним.
Кекс

Відповіді:


2208

Прочитайте її назад (як керується годинниковою стрілкою / правилом спіралі ):

  • int* - вказівник на int
  • int const * - вказівник на const int
  • int * const - const вказівник на int
  • int const * const - const покажчик на const int

Тепер перший constможе бути з обох боків типу, так:

  • const int * == int const *
  • const int * const == int const * const

Якщо ви хочете зійти з розуму, ви можете робити такі речі:

  • int ** - покажчик на покажчик на int
  • int ** const - const покажчик на покажчик на int
  • int * const * - вказівник на const вказівник на int
  • int const ** - покажчик на покажчик на const int
  • int * const * const - const покажчик на const покажчик на int
  • ...

І щоб переконатися, що ми зрозуміли сенс const:

int a = 5, b = 10, c = 15;

const int* foo;     // pointer to constant int.
foo = &a;           // assignment to where foo points to.

/* dummy statement*/
*foo = 6;           // the value of a can´t get changed through the pointer.

foo = &b;           // the pointer foo can be changed.



int *const bar = &c;  // constant pointer to int 
                      // note, you actually need to set the pointer 
                      // here because you can't change it later ;)

*bar = 16;            // the value of c can be changed through the pointer.    

/* dummy statement*/
bar = &a;             // not possible because bar is a constant pointer.           

fooє змінним покажчиком на постійне ціле число. Це дозволяє вам змінити те, на що ви вказуєте, але не значення, на яке ви вказуєте. Найчастіше це спостерігається з рядків у стилі С, де у вас є вказівник на a const char. Ви можете змінити, на який рядок ви вказуєте, але не можете змінити вміст цих рядків. Це важливо, коли сама рядок знаходиться в сегменті даних програми і не повинна змінюватися.

barє постійним або фіксованим вказівником на значення, яке можна змінити. Це як довідник без зайвого синтаксичного цукру. Через цей факт, як правило, ви б використовували посилання, де ви б використовували T* constвказівник, якщо вам не потрібно дозволити NULLвказівники.


481
Я хотів би додати велике правило, яке може допомогти вам запам'ятати, як дізнатись, чи 'const' застосовується до покажчика або до вказаних даних: розділіть оператор на знак asterix, тоді, якщо ключове слово const з'явиться в лівій частині (наприклад, у 'const int * foo') - він належить до загострених даних, якщо він знаходиться у правій частині ('int * const bar') - мова йде про покажчик.
Майкл

14
@Michael: Кудос Майклу за таке просте правило запам'ятовування / розуміння правила const.
sivabudh

10
@ Джефрі: читання його працює добре, доки немає дужок. Тоді добре ... використовуйте
typedefs

12
+1, хоча кращим підсумком буде: читання декларацій вказівника назад , це означає, близьке до заяви @Michael: зупиніть звичайне зчитування зліва направо на першій зірочці.
Вовк

3
@gedamial це робить, він працює чудово, але ви повинні призначити його одночасно з декларацією (оскільки ви не можете перепризначити "покажчик const"). const int x = 0; const int *const px = &x; const int *const *const p = &px;працює просто чудово.
RastaJedi

356

Для тих, хто не знає про годинникове / спіральне правило: Почніть з назви змінної, рухайтесь за годинниковою стрілкою (у цьому випадку рухайтеся назад) до наступного вказівника чи типу . Повторюйте, поки вираз не закінчиться.

Ось демонстрація:

покажчик на int

const покажчик на int const

покажчик на int const

покажчик на const int

const вказівник на int


8
@Jan посилання на складний приклад не має дозволів. чи можете ви опублікувати його тут або зняти обмеження на перегляд?
R71

8
@Rog у неї були всі дозволи на відкритий доступ ... На жаль, я не писав статті і не маю дозволів на доступ сам. Однак ось архівна версія статті, яка все ще працює: archive.is/SsfMX
Jan Rüegg

8
Складний приклад як і раніше праворуч ліворуч, але включає вирішення дужок так, як це було б нормально. Вся спіраль за годинниковою стрілкою не полегшує це.
Матвій

4
Остаточний приклад: void (*signal(int, void (*fp)(int)))(int);from archive.is/SsfMX
naXa

3
Не покладайтеся на це правило. Це не універсально. Є деякі випадки, коли це не вдається.
хакі

150

Я думаю, тут вже все відповіли, але я просто хочу додати, що ви повинні остерігатися typedefs! Вони НЕ просто заміни тексту.

Наприклад:

typedef char *ASTRING;
const ASTRING astring;

Тип astringє char * const, ні const char *. Це одна з причин, яку я завжди схильний ставити constправоруч від типу, і ніколи на початку.


20
І для мене це причина ніколи не вводити вказівники. Я не бачу користі в таких речах typedef int* PINT(я припускаю, що це щось, що випливало з практики в С і багато розробників продовжували це робити). Чудово, я замінив це *на P, це не прискорює введення тексту, а також вводить проблему, яку ви згадуєте.
Мефан

1
@Mephane - я це бачу. Однак мені здається, що на відміну від того, щоб уникнути гарної мовної функції, щоб продовжувати використовувати виняткове синтаксичне правило (про розміщення "const"), а не уникати використання виняткового синтаксичного правила, щоб ви могли безпечно використовувати цю мову .
ТЕД

6
@Mephane PINTнасправді є досить тупим використанням typedef, особливо тому, що це змушує мене думати, що системні магазини використовують пиво для пам’яті. typedef s, проте, дуже корисні для роботи з покажчиками на функції.
Наближення

5
@KazDragon ДЯКУЄМО! Без цього я б зіпсувався з усіма тими, що набрали типів PVOID, LPTSTRречі в програмі Win32 api!
Девід Лі

2
@Mephane: Мені довелося кілька разів використовувати pSomething при використанні певних макросів, які були записані для прийняття типу, але розпадалися б, якщо тип не був єдиним буквено-цифровим ідентифікатором. :)
Groo

56

Як і майже всі, хто зазначив:

У чому різниця між const X* p, X* const pі const X* const p?

Ви повинні прочитати декларації вказівників справа наліво.

  • const X* p означає "p вказує на X, що є const": об'єкт X не можна змінити через p.

  • X* const p означає "p - покажчик const на X, який не є const": ви не можете змінити сам вказівник p, але ви можете змінити X об'єкт через p.

  • const X* const p означає "p - покажчик const на X, який є const": ви не можете змінити сам вказівник p, а також не можете змінити X об'єкт через p.


3
Не забувайте, що const X* p;== X const * p;як в"p points to an X that is const": the X object can't be changed via p.
Джессі

просте і приємне пояснення!
Едісон Ло

50
  1. Постійна довідка:

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

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
  2. Постійні покажчики

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

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
  3. Вказівник на константу

    Покажчик, через який не можна змінити значення змінної, яку він вказує, відомий як покажчик на константу.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
  4. Постійний покажчик на константу

    Постійний вказівник на константу - це вказівник, який не може ні змінити адресу, на яку вказує, і не може змінити значення, збережене за цією адресою.

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error

20

Загальне правило полягає в тому, що constключове слово застосовується до того, що йому передує негайно. Виняток, початок constзастосовується до наступного.

  • const int*це те саме, що int const*і означає "вказівник на постійний int" .
  • const int* constце те саме, що int const* constі означає "постійний вказівник на постійний int" .

Редагувати: Що стосується Dos і Don'ts, якщо ця відповідь недостатня, ви могли б бути більш точними щодо того, що ви хочете?


19

Це питання показує , саме тому мені подобається робити речі так , як я вже згадував в моєму питанні є сопзЬ після типу ід прийнятним?

Коротше кажучи, я знаходжу найпростіший спосіб запам'ятати правило - це те, що "const" йде після того, що стосується. Отже, у вашому запитанні "int const *" означає, що int є постійним, тоді як "int * const" означатиме, що вказівник є постійним.

Якщо хтось вирішить поставити його в самий фронт (наприклад: "const int *"), як особливий виняток у цьому випадку він застосовується до речі після неї.

Багато людей люблять використовувати цей особливий виняток, тому що вони вважають, що це виглядає приємніше. Мені це не подобається, бо це виняток, і таким чином плутає речі.


2
Я розірваний у цьому питанні. Логічно це має сенс. Однак більшість розробників c ++ писали б, const T*і це стало більш природним. Як часто ви будь-коли користуєтесь T* const, як правило, посилання буде добре. Мене все це покусало один раз, коли хотів, boost::shared_ptr<const T>а натомість написав const boost::shared_ptr<T>. Це ж питання у дещо іншому контексті.
Метт Прайс

Насправді я використовую постійні покажчики частіше, ніж використовую константи. Крім того, ви повинні подумати про те, як ви збираєтеся реагувати за наявності покажчиків на вказівники (тощо). Імовірно, це рідше, але було б непогано подумати про речі таким чином, щоб ви могли вирішити ці ситуації за допомогою програми.
ТЕД

1
Ще однією приємною перевагою розміщення const праворуч від типу є те, що тепер усе ліворуч від будь- constякого типу є тим, що є const, і все праворуч - це те, що є насправді const. Візьмемо int const * const * p;як приклад. Ні, я зазвичай не пишу так, це лише приклад. По-перше const: введіть int, а int, що є const, - це вміст покажчика const, який є вмістом p. Другий const: type - вказівник на constint, const oblect - це вмістp
dgnuff

18

Просте використання const.

Найпростіше використання - оголосити названу константу. Для цього можна оголосити константу так, ніби вона була змінною, але додайте constперед нею. Треба негайно ініціалізувати його у конструкторі, оскільки, звичайно, не можна встановити значення пізніше, оскільки це змінило б його. Наприклад:

const int Constant1=96; 

створить цілу константу, немислено називається Constant1, зі значенням 96.

Такі константи корисні для параметрів, які використовуються в програмі, але їх не потрібно змінювати після складання програми. Він має перевагу для програмістів перед командою C препроцесора #defineтим, що він розуміється та використовується самим компілятором, а не просто замінюється в текст програми препроцесором до досягнення основного компілятора, тому повідомлення про помилки набагато корисніші.

Він також працює з покажчиками, але треба бути обережним, де constвизначити, чи вказівник чи те, на що він вказує, є постійним або обом. Наприклад:

const int * Constant2 

оголошує, що Constant2є змінним покажчиком на постійне ціле число і:

int const * Constant2

є альтернативним синтаксисом, який робить те саме, тоді як

int * const Constant3

оголошує, що Constant3є постійним вказівником на змінну ціле число і

int const * const Constant4

оголошує, що Constant4є постійним вказівником на постійне ціле число. В основному "const" поширюється на те, що знаходиться в його безпосередній лівій частині (за винятком випадків, якщо там немає нічого, і в цьому випадку це стосується того, що є його безпосереднім правом).

посилання: http://duramecho.com/ComputerInformation/WhyHowCppConst.html


9

У мене були ті самі сумніви, що і у вас, поки я не натрапив на цю книгу Гуру С ++ Скотт Майерс. Зверніться до третього пункту цієї книги, де він детально розповідає про використання const.

Просто дотримуйтесь цієї поради

  1. Якщо слово constз’являється зліва від зірочки, те, на що вказується, є постійним
  2. Якщо слово constз’являється праворуч від зірочки, сам вказівник є постійним
  3. Якщо constз'являється з обох сторін, обидва є постійними

7

Це просто, але хитро. Зверніть увагу, що ми можемо поміняти місцямиconst класифікатор з будь-яким типом даних ( int, char, floatі т.д.).

Подивимося нижче на прикладі.


const int *p ==> *p є лише для читання [ pє вказівником на постійне ціле число]

int const *p ==> *p є лише для читання [ pє вказівником на постійне ціле число]


int *p const ==> Неправильна заява. Компілятор видає синтаксичну помилку.

int *const p==> pлише для читання [p є постійним вказівником на ціле число]. Оскільки вказівник pтут є лише для читання, декларація та визначення повинні знаходитися на одному місці.


const int *p const ==> Неправильна заява. Компілятор видає синтаксичну помилку.

const int const *p ==> *pлише для читання

const int *const p1 ==> *pі pє лише для читання [ pє постійним вказівником на постійне ціле число]. Як вказівникpтут є лише для читання, декларація та визначення повинні знаходитися на одному місці.


int const *p const ==> Неправильно заява. Компілятор видає синтаксичну помилку.

int const int *p ==> Неправильно заява. Компілятор видає синтаксичну помилку.

int const const *p ==> *pє лише для читання і еквівалентноint const *p

int const *const p ==> *pі pє лише для читання [ pє постійним вказівником на постійне ціле число]. Оскільки вказівник pтут є лише для читання, декларація та визначення повинні знаходитися на одному місці.


6

Існує багато інших тонких моментів, що оточують правильність const у C ++. Я припускаю, що тут питання стосувалося просто C, але я наведу кілька прикладних прикладів, оскільки тег є C ++:

  • Ви часто TYPE const &передаєте великі аргументи, такі як рядки, оскільки це не дозволяє модифікувати або скопіювати об'єкт. Приклад:

    TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }

    Але TYPE & constбезглуздо, оскільки посилання завжди const.

  • Ви завжди повинні позначати методи класу, які не змінюють клас як const, інакше ви не можете викликати метод із TYPE const &посилання. Приклад:

    bool TYPE::operator==(const TYPE &rhs) const { ... }

  • Існують загальні ситуації, коли і повертане значення, і метод повинні бути const. Приклад:

    const TYPE TYPE::operator+(const TYPE &rhs) const { ... }

    Насправді, методи const не повинні повертати дані внутрішнього класу як посилання на не-const.

  • Як результат, часто потрібно створювати як const, так і non-const метод, використовуючи const перевантаження. Наприклад, якщо ви визначаєте T const& operator[] (unsigned i) const;, ви, ймовірно, також захочете не-const версію, надану:

    inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }

У Afaik, у C немає функцій const, функції, які не є членами, самі по собі не можуть бути const у C ++, методи const можуть мати побічні ефекти, а компілятор не може використовувати const функції, щоб уникнути дублювання викликів функції. Насправді навіть проста int const &посилання може свідчити про те, що значення, на яке воно посилається, може бути змінено в іншому місці.


6

Синтаксис декларацій C і C ++ неодноразово описувався як невдалий експеримент оригінальними дизайнерами.

Натомість назвемо тип «покажчик на Type»; Я назву це Ptr_:

template< class Type >
using Ptr_ = Type*;

Тепер Ptr_<char>є вказівник на char.

Ptr_<const char>- покажчик на const char.

І const Ptr_<const char>є constвказівником на const char.

Там.

введіть тут опис зображення


3
у вас є цитата до першого речення?
sp2danny

@ sp2danny: Гуглінг "Синтаксис невдалого експерименту" лише відкашлює ряд інтерв'ю з Bjarne Stroustrup, де він висловлює свою думку в цьому напрямку, наприклад "Я вважаю синтаксис декларатора C експериментом, який не вдався" в інтерв'ю Slashdot. Тому я не маю посилання на претензію на точки зору оригінальних дизайнерів C. Я думаю, що це може бути знайдено досить сильними науково-дослідними зусиллями, або, можливо, спростується, просто запитавши їх, але я вважаю, що краще, як зараз. з тією частиною претензії, як і раніше, невирішеною і, ймовірно, правдою :)
Привіт і чт. - Альф

1
"Синтаксис оголошень C і C ++ неодноразово описувався як невдалий експеримент оригінальними дизайнерами." неправильно для C, будь ласка, змініть своє речення щодо C або надайте кілька цитат.
Stargateur

3
@Stargateur: Мабуть, ви прочитали попередні коментарі та знайшли щось, що могли б використати для педантизму. Успіхів у вашому житті. У всякому разі, старожили, як я, пам’ятають багато, що ми не можемо довести, не займаючись дуже трудомісткими дослідженнями. Ви можете просто прийняти моє слово.
ура та хт. - Альф

1
@Stargateur " Сетхі (...) зауважив, що багато вкладених оголошень і виразів стануть простішими, якби оператор опосередкування був прийнятий за оператор постфікса замість префікса, але до цього часу вже було пізно змінити". походить від DMR. Звичайно, DMR не винайшов const та мінливі ключові слова, вони походять із C ++ / X3J11, про що свідчить на цій сторінці.
Антті

6

Для мене позиція, constтобто, чи є вона лівою або правою, або лівою та правою щодо відносно, *допомагає мені з'ясувати фактичне значення.

  1. A constвліво *означає, що об'єкт, на який вказує вказівник, є constоб'єктом.

  2. А constвправо *означає, що вказівник є constвказівником.

Наступна таблиця взята із стандартного зчитувача курсу лабораторій програмування C ++ Stanford CS106L.

введіть тут опис зображення


3

Це здебільшого стосується другого рядка: найкращі практики, завдання, параметри функцій тощо.

Загальна практика. Спробуйте зробити все, constщо можете. Або, якщо сказати іншим способом, зробити все constдля початку, а потім видалити саме мінімальний набірconst s, необхідний для того, щоб програма могла функціонувати. Це буде великою підмогою у досягненні коректності const та допоможе забезпечити, щоб тонкі помилки не вводилися, коли люди намагаються привласнювати речі, які вони не повинні змінювати.

Уникайте const_cast <>, як чума. Є один або два законні випадки використання для цього, але їх дуже мало і між ними. Якщо ви намагаєтесь змінити constоб'єкт, ви зробите набагато краще, щоб знайти того, хто заявив про це constв першому темпі, і поговоріть з ними справу, щоб досягти консенсусу щодо того, що має статися.

Що веде дуже акуратно до виконання завдань. Ви можете призначити щось, лише якщо це не const. Якщо ви хочете призначити щось, що є const, див. Вище. Пам'ятайте, що в деклараціях є int const *foo;і int * const bar;різні речіconst - інші відповіді тут висвітлювали це питання із захопленням, тому я не буду в цьому займатися.

Параметри функції:

Передайте значення: наприклад, void func(int param)вам не байдуже в той чи інший спосіб на веб-сайті, що телефонує. Можна зробити аргумент, що є випадки використання для оголошення функції як, void func(int const param)але це не впливає на абонента, лише на саму функцію, оскільки те, яке значення передане, не може бути змінено функцією під час виклику.

Пройти за посиланням: наприклад, void func(int &param)зараз це має значення. Оскільки щойно оголошені funcдозволено змінюватись param, і будь-який сайт, що телефонує, повинен бути готовий боротися з наслідками. Зміна декларації на void func(int const &param)зміну договору та гарантії, які funcтепер не можуть змінитисяparam , тобто передається те, що вийде. Як зазначають інші, це дуже корисно для дешевого проходження великого об'єкта, який ви не хочете змінювати. Пройти еталон набагато дешевше, ніж передавати великий об'єкт за значенням.

Проходить покажчик: наприклад , void func(int *param)і void func(int const *param)ці два досить багато синонімів їх позиційні колегами, з одним застереженням , що викликається, тепер необхідно перевірити , nullptrякщо деякі інші договірні гарантії запевняють , funcщо він ніколи не отримає nullptrвparam .

Оглядова стаття на цю тему. Довести правильність у подібній справі пекельно важко, просто помилково помилитися. Тому не ризикуйте і завжди перевіряйте параметри вказівника на nullptr. Ви вбережете себе від болю та страждань та важко знайти помилок у довгостроковій перспективі. А що стосується вартості чека, то це бруд дешевий, а у випадках, коли статичний аналіз, вбудований у компілятор, може керувати ним, оптимізатор все-таки зможе схилити його. Увімкніть генерацію часового коду посилання для MSVC або WOPR (я думаю) для GCC, і ви отримаєте програму широко, тобто навіть у викликах функцій, які перетинають межу модуля вихідного коду.

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


3

Const з int з обох сторін зробить покажчик на постійний int :

const int *ptr=&i;

або:

int const *ptr=&i;

constпісля *зробить постійний покажчик на int :

int *const ptr=&i;

У цьому випадку всі вони вказують на постійне ціле число , але жодне з них не є постійним вказівником:

 const int *ptr1=&i, *ptr2=&j;

У цьому випадку всі вказують на постійне ціле число, а ptr2 - постійний покажчик на постійне ціле число . Але ptr1 не є постійним покажчиком:

int const *ptr1=&i, *const ptr2=&j;

3
  • якщо constце зліва від *, воно відноситься до значення (це не має значення , чи є це const intабо int const)
  • якщо constце справа від *, це відноситься до самого вказівником
  • це може бути і те й інше

Важливий момент: const int *p не означає, що значення, на яке ви посилаєтесь, є постійним !! . Це означає, що ви не можете змінити його через цей покажчик (тобто ви не можете призначити $ * p = ... `). Саме значення може бути змінено іншими способами. Напр

int x = 5;
const int *p = &x;
x = 6; //legal
printf("%d", *p) // prints 6
*p = 7; //error 

Це означає, що використовується в основному у підписах функцій, щоб гарантувати, що функція не може випадково змінити передані аргументи.


2

Просто задля повноти для C, дотримуючись пояснень інших, не впевнений у C ++.

  • pp - покажчик на покажчик
  • p - покажчик
  • дані - річ, вказана на прикладах x
  • жирний - змінна лише для читання

Покажчик

  • p дані - int *p;
  • p дані -int const *p;
  • p дані -int * const p;
  • p дані -int const * const p;

Вказівник на вказівник

  1. pp p даних - int **pp;
  2. pp p даних -int ** const pp;
  3. pp p даних -int * const *pp;
  4. pp p даних -int const **pp;
  5. pp p даних -int * const * const pp;
  6. pp p даних -int const ** const pp;
  7. pp p даних -int const * const *pp;
  8. pp p даних -int const * const * const pp;
// Example 1
int x;
x = 10;
int *p = NULL;
p = &x;
int **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 2
int x;
x = 10;
int *p = NULL;
p = &x;
int ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 3
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 4
int const x = 10; // Definition must happen during declaration
int const * p = NULL;
p = &x;
int const **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 5
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 6
int const x = 10; // Definition must happen during declaration
int const *p = NULL;
p = &x;
int const ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 7
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 8
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

N-рівнів відхилення

Просто продовжуйте, але може людство відлучити вас.

int x = 10;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
int ****pppp = &ppp;

printf("%d \n", ****pppp);

0
  1. const int*- вказівник на постійний intоб'єкт.

Ви можете змінити значення вказівника; не можна змінювати значення intоб’єкта, на який вказує вказівник.


  1. const int * const- постійний вказівник на постійний intоб'єкт.

Ви не можете змінити значення вказівника, а також значення intоб'єкта, на який вказує вказівник.


  1. int const *- вказівник на постійний intоб'єкт.

Це твердження еквівалентно 1. const int* - Ви можете змінити значення вказівника, але ви не можете змінити значення intоб'єкта, на який вказує вказівник.


Насправді, є четвертий варіант:

  1. int * const - постійний покажчик на int об’єкт.

Ви можете змінити значення об'єкта, на який вказує вказівник, але ви не можете змінити значення самого вказівника. Вказівник завжди вказуватиме на один і той же intоб’єкт, але це значення цьогоint об'єкта можна змінити.


Якщо ви хочете визначити певний тип конструкції C або C ++, ви можете скористатися правилом годинникової / спіральної дії, виготовленим Девідом Андерсоном; але не плутати з правилом Андерсона, зробленим Россом Дж. Андерсоном, що є чимось досить виразним.

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