В чем разница между const int *, const int * const и int const *?

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

Я хочу знать все, что можно и чего нельзя делать с точки зрения назначений, передачи функций и т. Д.

17.07.2009 13:28:09
Вы можете использовать «Правило по часовой стрелке / спирали», чтобы расшифровать большинство объявлений C и C ++.
James McNellis 13.06.2010 20:49:16
cdecl.org - это отличный веб-сайт, который автоматически переводит объявления C для вас.
Dave Gallagher 2.11.2010 19:37:45
@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. Каким будет эквивалентное однострочное объявление на легкочитаемом языке, таком как Паскаль?
Mark K Cowan 9.07.2015 17:08:08
@MarkKCowan В Паскале это было бы что-то вроде function(x:^char):^int. Там типы функций подразумевают указатель на функцию, поэтому нет необходимости указывать ее, и Паскаль не обеспечивает константную корректность. Это можно прочитать слева направо.
Calmarius 9.07.2015 20:54:00
Первое, что находится слева от «const» - это то, что постоянно. Если «const» - это самое дальнее слева, то первое, что справа от него, является постоянным.
Cupcake 31.07.2016 04:41:59
18 ОТВЕТОВ
РЕШЕНИЕ

Прочитайте это в обратном направлении (как управляется по часовой стрелке / правилу спирали ):

  • int* - указатель на int
  • int const * - указатель на const int
  • int * const - константный указатель на int
  • int const * const константный указатель на const int

Теперь первый constможет быть с любой стороны типа так:

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

Если вы хотите сойти с ума, вы можете сделать что-то вроде этого:

  • int ** - указатель на указатель на int
  • int ** const - константный указатель на указатель на int
  • int * const * - указатель на константный указатель на int
  • int const ** - указатель на указатель на const int
  • int * 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переменный указатель на постоянное целое число Это позволяет вам изменить то, на что вы указываете, но не значение, на которое вы указываете. Чаще всего это наблюдается в строках в стиле C, где у вас есть указатель на a const char. Вы можете изменить строку, на которую вы указываете, но вы не можете изменить содержимое этих строк. Это важно, когда сама строка находится в сегменте данных программы и не должна изменяться.

barпостоянный или фиксированный указатель на значение, которое можно изменить. Это как ссылка без лишнего синтаксического сахара. Из-за этого обычно вы используете ссылку, в которой вы используете T* constуказатель, если вам не нужно разрешать NULLуказатели.

2180
7.02.2020 15:45:34
Я хотел бы добавить практическое правило, которое может помочь вам вспомнить, как определить, относится ли «const» к указателю или к указанным данным: затем разбить оператор по знаку звездочки, если ключевое слово const появляется в левой части (как в 'const int * foo') - он принадлежит указанным данным, если он находится в правой части ('int * const bar') - это указатель.
Michael 17.07.2009 17:26:53
@Michael: Слава Майкл за такое простое правило для запоминания / понимания const правило.
sivabudh 11.02.2010 19:00:31
@Jeffrey: чтение в обратном направлении работает хорошо, пока нет скобок. Тогда, ну ... используйте typedefs
Mooing Duck 28.05.2013 19:53:36
+1, хотя лучше бы подвести итоги: прочитать объявления указателей в обратном направлении , то есть близко к утверждению @Michael: остановить нормальное чтение слева направо на первой звездочке.
Wolf 18.06.2014 09:21:28
@gedamial это делает, он работает нормально, но вы должны назначить его одновременно с объявлением (потому что вы не можете переназначить «указатель констант»). const int x = 0; const int *const px = &x; const int *const *const p = &px;работает просто отлично.
RastaJedi 8.08.2016 23:15:10

Общее правило заключается в том, что constключевое слово применяется к тому, что ему предшествует. Исключение, начало constотносится к тому, что следует.

  • const int*то же, что int const*и означает «указатель на константу int» .
  • const int* constэто то же самое, что int const* constи означает «постоянный указатель на константу int» .

Редактировать: Для того, что можно и чего нельзя делать, если этого ответа недостаточно, не могли бы вы быть более точным относительно того, что вы хотите?

20
17.04.2018 05:13:33

Простое использование 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

18
8.06.2019 06:55:07

Как почти все отметили:

В чем разница const X* p, X* const pа const X* const p?

Вы должны прочитать объявления указателя справа налево.

  • const X* p означает «p указывает на постоянный X»: объект X нельзя изменить с помощью p.

  • X* const p означает «p является константным указателем на X, который не является константным»: вы не можете изменить сам указатель p, но вы можете изменить X-объект через p.

  • const X* const p означает «p является константным указателем на X, который является константой»: вы не можете изменить сам указатель p, а также не можете изменить объект X с помощью p.

56
26.05.2017 14:20:07
Не забывайте, что const X* p;== X const * p;как в"p points to an X that is const": the X object can't be changed via p.
Jesse Chisholm 17.01.2019 20:06:58
простое и приятное объяснение!
Edison Lo 17.09.2019 15:05:29

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

Например:

typedef char *ASTRING;
const ASTRING astring;

Тип astringесть char * const, нет const char *. Это одна из причин, которую я всегда склоняю constсправа от шрифта, и никогда в начале.

149
17.04.2018 05:15:35
И для меня это причина никогда не указывать указатели. Я не вижу преимущества в таких вещах, как typedef int* PINT(я предполагаю, что это то, что пришло из практики в C, и многие разработчики продолжали делать это). Отлично, я заменил это *на P, это не ускоряет ввод текста, а также представляет проблему, о которой вы упомянули.
Mephane 28.01.2011 13:01:06
@Mephane - я это вижу. Тем не менее, мне кажется, что в некотором роде следует избегать хорошей языковой функции, чтобы продолжать использовать исключительное синтаксическое правило (о размещении "const"), вместо того, чтобы избегать использования исключительного синтаксического правила, чтобы вы могли безопасно использовать эту языковую функцию ,
T.E.D. 17.10.2012 14:06:02
@Mephane PINT- действительно довольно глупое использование typedef, особенно потому, что оно заставляет меня думать, что системные магазины используют пиво для памяти. Однако typedef довольно полезны для работы с указателями на функции.
ApproachingDarknessFish 26.12.2013 21:07:47
@KazDragon СПАСИБО! Без него я бы перепутались со всеми теми typedefed PVOID, LPTSTRвещи в Win32 API!
David Lee 8.05.2014 12:29:28
@Mephane: мне приходилось пару раз использовать pSomething при использовании определенных устаревших макросов, которые были написаны для принятия типа, но распадались бы на части, если бы тип не был единственным буквенно-цифровым идентификатором. :)
Groo 8.05.2017 16:37:00

Этот вопрос показывает , именно поэтому мне нравится делать вещи так , как я уже упоминал в моем вопросе является сопзЬ после типа ид приемлемым?

Короче говоря, я считаю, что самый простой способ запомнить правило - это то, что «const» идет после того, к чему оно относится. Итак, в вашем вопросе «int const *» означает, что int является константой, а «int * const» будет означать, что указатель является константой.

Если кто-то решит поместить его на передний план (например, «const int *»), в качестве особого исключения в этом случае он применяется к предмету после него.

Многим людям нравится использовать это специальное исключение, потому что они думают, что это выглядит лучше. Мне это не нравится, потому что это исключение и, таким образом, все путает.

19
23.05.2017 12:02:47
Я разрываюсь в этом вопросе. Логически это имеет смысл. Однако большинство разработчиков на С ++ писали бы, const T*и это стало более естественным. Как часто вы когда-либо используете в T* constлюбом случае, обычно справка будет хорошо. Я получил все это один раз, когда захотел boost::shared_ptr<const T>и вместо этого написал const boost::shared_ptr<T>. Та же проблема в несколько ином контексте.
Matt Price 17.07.2009 14:08:15
На самом деле, я использую постоянные указатели чаще, чем постоянные. Кроме того, вам нужно подумать о том, как вы будете реагировать в присутствии указателей на указатели (и т. Д.). Конечно, они встречаются реже, но было бы неплохо подумать о вещах таким образом, чтобы вы могли справиться с этими ситуациями с апломбом.
T.E.D. 17.07.2009 14:19:20
Еще одно приятное преимущество размещения const справа от типа состоит в том, что теперь все слева от любого constявляется типом того, что является const, а все его права - тем, что на самом деле является const. Взять хотя int const * const * p;бы пример. Нет, я обычно так не пишу, это всего лишь пример. Первый const: введите int, и int, который является const, является содержимым указателя const, который является содержимым p. Второй const: type - указатель на constint, const oblect - содержимоеp
dgnuff 15.03.2018 07:18:06

Есть много других тонких моментов, касающихся правильности констант в C ++. Я предполагаю, что вопрос здесь был просто о C, но я приведу несколько связанных примеров, так как тег C ++:

  • Вы часто передаете большие аргументы, такие как строки, поскольку TYPE const &это предотвращает изменение или копирование объекта. Пример :

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

    Но TYPE & constэто бессмысленно, потому что ссылки всегда постоянны.

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

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

  • Есть общие ситуации, когда и возвращаемое значение, и метод должны быть постоянными. Пример :

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

    Фактически, методы const не должны возвращать данные внутреннего класса как ссылку на неконстантную.

  • В результате часто приходится создавать как константный, так и неконстантный метод с использованием константной перегрузки. Например, если вы определите T const& operator[] (unsigned i) const;, то вы, вероятно, также захотите неконстантную версию, заданную как:

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

На самом деле, в C нет константных функций, функции, не являющиеся членами, сами по себе не могут быть константными в C ++, методы const могут иметь побочные эффекты, а компилятор не может использовать функции const, чтобы избежать дублирования вызовов функций. Фактически, даже простая int const &ссылка может свидетельствовать об изменении значения, на которое она ссылается, в другом месте.

6
13.09.2011 10:50:54
  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
50
13.03.2015 19:32:44

Это просто, но сложно. Пожалуйста , обратите внимание , что мы можем поменять 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здесь только для чтения, объявление и определение должны быть в одном месте.

7
17.08.2015 21:12:24

У меня были те же сомнения, что и у вас, пока я не наткнулся на эту книгу Гуру С ++ Скотта Мейерса. Обратитесь к третьему пункту в этой книге, где он подробно рассказывает об использовании const.

Просто следуйте этому совету

  1. Если слово constпоявляется слева от звездочки, на что указывает постоянная
  2. Если слово constпоявляется справа от звездочки, сам указатель является постоянным
  3. Если constпоявляется с обеих сторон, оба являются постоянными
9
21.03.2015 13:56:12

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

Вот демо:

указатель на int

const указатель на int const

указатель на int const

указатель на const int

константный указатель на int

351
8.06.2019 06:53:19
@ Ян ссылка на сложный пример не имеет разрешений. Вы можете опубликовать его прямо здесь или снять ограничения на просмотр?
R71 8.04.2016 12:03:44
@ Раньше у него были все права на открытый доступ ... Я не писал статью и у меня, к сожалению, нет прав доступа. Однако, вот архивированная версия статьи, которая все еще работает: archive.is/SsfMX
Jan Rüegg 8.04.2016 13:34:41
Сложный пример по-прежнему справа налево, но включает в себя разрешение скобок, как обычно. Вся эта спираль по часовой стрелке не делает это легче.
Matthew Read 18.09.2016 23:04:27
Окончательный пример: void (*signal(int, void (*fp)(int)))(int);из
naXa 3.05.2017 19:04:49
Не полагайтесь на это правило. Это не универсально. Есть несколько случаев, когда это не удается.
haccks 12.05.2017 07:17:04

Синтаксис объявления 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.

Там.

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

6
6.01.2016 00:18:21
у вас есть цитата для первого предложения?
sp2danny 14.09.2016 07:20:05
@ sp2danny: поиск в Google «эксперимент с синтаксисом С потерпел неудачу» только кашляет во многих интервью с Бьярном Страуструпом, где он выражает свое мнение в этом направлении, например «Я считаю, что синтаксис декларатора С эксперимент не удался» в интервью Slashdot. Таким образом, у меня нет ссылки на утверждение о точках зрения оригинальных дизайнеров C. Я думаю, что это может быть найдено достаточно сильными исследовательскими усилиями или, возможно, опровергнуто, просто спросив их, но я думаю, что это лучше, чем сейчас. с этой частью претензии, все еще не определились и, скорее всего, правда :)
Cheers and hth. - Alf 14.09.2016 10:42:47
«Синтаксис объявления C и C ++ неоднократно описывался как неудачный эксперимент оригинальными дизайнерами». неправильно для C, пожалуйста, измените свое предложение о C или предоставьте некоторые цитаты.
Stargateur 1.01.2018 14:22:05
@Stargateur: Видимо, вы прочитали предыдущие комментарии и нашли что-то, что вы могли бы использовать для педантизма. Удачи в твоей жизни. В любом случае, старожилы, подобные мне, многое помнят, что мы не можем доказать, не занимаясь очень трудоемкими исследованиями. Ты можешь просто поверить мне на слово.
Cheers and hth. - Alf 1.01.2018 14:25:33

В основном это касается второй строки: лучшие практики, назначения, параметры функций и т. Д.

Общая практика. Попробуйте сделать все, constчто вы можете. Или, говоря иначе, сделайте все constдля начала, а затем удалите точно минимальный набор consts, необходимый для работы программы. Это будет большим подспорьем в достижении константности и поможет гарантировать, что незаметные ошибки не появятся, когда люди попытаются заняться вещами, которые они не должны изменять.

Избегайте const_cast <>, как чума. Есть один или два законных варианта использования, но их очень мало и они далеко друг от друга. Если вы пытаетесь изменить 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
15.03.2018 07:59:23

Константа с int с обеих сторон сделает указатель на константу int :

const int *ptr=&i;

или:

int const *ptr=&i;

constafter *сделает постоянный указатель на int :

int *const ptr=&i;

В этом случае все они являются указателями на постоянное целое число , но ни один из них не является постоянным указателем:

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

В этом случае все являются указателями на постоянное целое число, а ptr2 является постоянным указателем на постоянное целое число . Но ptr1 не является постоянным указателем:

int const *ptr1=&i, *const ptr2=&j;
3
8.06.2019 06:51:39

Для меня позиция, constто есть, кажется ли она ЛЕВОЙ или ПРАВОЙ или ЛЕВОЙ и ПРАВОЙ относительно, *помогает мне понять фактическое значение.

  1. A constLEFT *означает, что объект, на который указывает указатель, является constобъектом.

  2. От А constдо ПРАВА *указывает, что указатель является constуказателем.

Следующая таблица взята из Stanford CS106L Standard C ++ Programming Laboratory Reader.

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

6
4.02.2019 07:48:16

Просто ради полноты для C, следуя другим объяснениям, не уверен для C ++.

  • pp - указатель на указатель
  • р - указатель
  • данные - вещь указанная, в примерах x
  • полужирный - переменная только для чтения

Указатель

  • р данные - int *p;
  • р данные -int const *p;
  • р данные -int * const p;
  • р данные -int const * const p;

Указатель на указатель

  1. pp p data - int **pp;
  2. pp p data -int ** const pp;
  3. pp p data -int * const *pp;
  4. pp p data -int const **pp;
  5. pp p data -int * const * const pp;
  6. pp p data -int const ** const pp;
  7. pp p data -int const * const *pp;
  8. pp p data -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);
2
8.06.2019 06:50:36
  • если 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 

Это предназначено для использования в основном в сигнатурах функций, чтобы гарантировать, что функция не может случайно изменить переданные аргументы.

3
24.09.2019 10:21:14
  1. const int*указатель на постоянный intобъект.

Вы можете изменить значение указателя; Вы не можете изменить значение intобъекта, на который указывает указатель.


  1. const int * constпостоянный указатель на постоянный intобъект.

Вы не можете изменить значение указателя или значение intобъекта, на который указывает указатель.


  1. int const *указатель на постоянный intобъект.

Это утверждение эквивалентно 1. const int*- Вы можете изменить значение указателя, но вы не можете изменить значение intобъекта, на который указывает указатель.


На самом деле, есть 4-й вариант:

  1. int * constпостоянный указатель на intобъект.

Вы можете изменить значение объекта, на который указывает указатель, но вы не можете изменить значение самого указателя. Указатель всегда будет указывать на один и тот же intобъект, но это значение этого intобъекта можно изменить.


Если вы хотите определить определенный тип конструкции C или C ++, вы можете использовать Правило по часовой стрелке / спирали, разработанное Дэвидом Андерсоном; но не путать с правилом Андерсона, сформулированным Россом Дж. Андерсоном, который является чем-то совершенно отличным.

0
7.02.2020 14:45:40