Что произойдет, если мы присвоим нуль указателю?

Это означает, что вы можете написать int *p = 0;, но не int *p = 5;

Friedrich 20.08.2023 15:47

В этом вопросе/ответе объясняется связь между нулевым двоичным значением и нулевым указателем: stackoverflow.com/questions/69211439/…

nielsen 20.08.2023 16:20
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
87
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это просто означает, что компилятор C должен обрабатывать буквальное целочисленное значение 0, чтобы указать указатель NULL.

то есть

int * x = 0;

и

int * x = NULL;

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

Ответ принят как подходящий

Что означает преобразование нуля в указатель соответствующего типа?

Целочисленная константа ноль обрабатывается особым образом; когда он преобразуется в указатель, результатом является нулевой указатель. Нулевой указатель — это специальное значение, означающее, что указатель не указывает ни на какой объект или функцию.

Можно ли преобразовать значение типа?

Преобразования в C — это преобразования типов. Как правило, преобразование — это функция или операция, которая принимает значение одного типа и возвращает такое же значение другого типа, если это возможно. (Если значение не может быть представлено в результирующем типе, преобразование должно в каком-то смысле давать ближайшее представимое значение.)

Например, когда значение int три преобразуется в short, результат равен трем. Когда он преобразуется в float, результат равен трем. Когда значение float 3,5 преобразуется в int, результат не может быть 3,5, поскольку 3,5 не может быть представлено в int. Вместо этого создается число три, которое является ближайшим представимым значением в направлении к нулю.

Когда ноль преобразуется в указатель, его значение «ничего» сохраняется, поскольку результирующий указатель, нулевой указатель, указывает на «ничего».

«… Значение 0 — это единственное целочисленное значение, которое можно присвоить непосредственно переменной-указателю».

Это не очень хорошо сказано. Технически это не правильно. Правила стандарта C для оператора присваивания рассматривают постоянное целочисленное значение нуля как особое и позволяют присваивать его указателю без предупреждения. Это сделано для того, чтобы указатели могли быть установлены на нулевое значение указателя с кодом, подобным p = 0;.

Утверждение неверно, потому что это верно только для целочисленных констант. В int x = 0; char *p = x;x не подлежит этому специальному обращению, так как это переменная, а не константа. Правила стандарта C требуют, чтобы реализация C выдавала для этого диагностическое сообщение.

Целые числа, отличные от нуля, могут быть преобразованы в тип указателя с помощью приведения. Стандарт C не полностью определяет, как работают эти преобразования. В частности, когда непостоянное выражение с нулевым значением преобразуется в указатель, стандарт не гарантирует, что он создаст нулевой указатель. Это происходит в большинстве реализаций C, но стандарт C не требует этого. Большинство реализаций C определяют преобразования между целыми числами и указателями для работы обычным способом, который вы ожидаете от схемы адресации памяти основного оборудования. В таких реализациях вы можете преобразовать целочисленное значение, являющееся адресом памяти, в указатель, и результатом будет указатель на этот адрес. Однако правила использования таких преобразований несколько усложняются, если принять во внимание все правила стандарта C.

Большое спасибо! 😊

Osmium 22.08.2023 14:34

Кратко:

  • Любой тип указателя на «что-то» может превратить свое значение в нулевой указатель, то есть указатель, указывающий в четко определенное «никуда».
  • Когда указатель является нулевым указателем, он имеет своего рода волшебное внутреннее представление, о котором нам, программистам, предположительно не следует волноваться. Скорее всего на большинстве систем все нули, но теоретически может быть и что-то другое.
  • Чтобы превратить что-то в нулевой указатель, нам нужно инициализировать/присвоить константу нулевого указателя нашей переменной указателя. Допустимыми константами нулевого указателя в C являются 0, (void*)0) или какое-либо другое выражение времени компиляции, приводящее к постоянному выражению с нулевым значением (например, 0L или 0+0 и т. д.).
  • Нулевой указатель не должен быть разыменован, но его можно сравнить с другими указателями или с константой нулевого указателя, чтобы проверить, является ли он нулевым указателем или нет.
  • Для удобства заголовок стандартной библиотеки stddef.h предоставляет заранее созданную константу нулевого указателя NULL, которая является предпочтительным и самодокументированным способом превратить что-либо в нулевой указатель или использовать при проверке, является ли что-либо нулевым указателем.
  • (Грядущий C23 добавляет новое ключевое слово nullptr, имеющее в основном то же значение и функцию, что и NULL, хотя оно доступно без включения какого-либо заголовка.)

«Язык-адвокат»/грязные подробности:

Что касается преобразований, то во время инициализации и/или присвоения переменных применяются «правила простого присвоения», найденные в стандарте C в C17 6.5.16.1, где говорится одно такое правило допустимого присвоения (выделено мной):

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

Поскольку это допустимая форма присваивания, следующее правило преобразования:

В простом присваивании (=) значение правого операнда преобразуется в тип присваивания выражение и заменяет значение, хранящееся в объекте, обозначенном левым операндом.

Фактическое преобразование затем описано в C17 6.3.2.3:

Целочисленное константное выражение со значением 0 или такое выражение, приведенное к типу void *, называется константой нулевого указателя. Если константа нулевого указателя преобразуется в тип указателя, результирующий указатель, называемый нулевым указателем, гарантированно будет сравниваться с неравным указателю на любой объект или функцию.

Преобразование нулевого указателя в другой тип указателя дает нулевой указатель этого типа. Любые два нулевых указателя должны сравниваться как равные.

Ваш ответ полезен. Большое спасибо.

Osmium 22.08.2023 14:33

Другие вопросы по теме