Ищу объяснение инициализации указателя на const int и int

#c #pointers #initialization #constants #constexpr

#c #указатели #инициализация #константы #constexpr

Вопрос:

Я работал над упражнениями в C Primer и нашел онлайн-решения для упражнения 2.32.

Я понял, что следующий код был незаконным, потому что инициализация не может преобразовать из int в int*:

int null = 0, *p = null;

Однако два из упомянутых решений, которые я не придумал, были:

     const int null3 = 0, *p3 = null3;
    
    constexpr int null4 = 0, *p4 = null4;
 

Почему это позволяет это во время компиляции без ошибок? Я все еще ожидал, что инициализация p3 и p4 потребует amp; для обозначения адреса (amp;null3, amp;null4).

Вот код, который у меня есть из моего файла notepad:

 
#include <iostream>

int main()
{

//  int null = 0, *p = null; // it is not legal; depending on intent there are two ways to fix (that I can think off atm)

    {
    int null = 0, *p = amp;null; // if the goal is to point to 'null'
    }
    {
    int null2 = 0, *p2 = 0; // if the goal is to create a nullptr
    }
    {
    const int null3 = 0, *p3 = null3; // if the goal is to create a nullptr
    }
    {
    constexpr int null4 = 0, *p4 = null4; // if the goal is to create a nullptr
    }

return 0;
}
 

Когда я запускаю через Microsoft Visual Studio CMDPrompt, это позволяет мне выполнять упражнение «cl» 2.32.cpp «»безошибочно.

Комментарии:

1. const int null3 = 0, *p3 = null3; это все еще выдает ошибку вы уверены, что она компилируется?

2. без ошибок? Я не нашел компилятора, который его принимает: godbolt.org/z/aK1Gvz . Какой компилятор вы используете?

3. @D’Kayd: это не должно компилироваться.

4. абсолютно @Bathsheba

Ответ №1:

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

Компилятор, совместимый со стандартами, должен выдавать диагностику для присвоения типа указателя на null3 и null4 . (Он также должен выдать диагностику для int *p = 0; .) Если у вас этого не происходит, проверьте, установлены ли соответствующие флаги компилятора.

Использование nullptr намного лучше, хотя:

 int *p = nullptr;
 

Комментарии:

1. «присвоить тип указателя null3 » Я всегда путаюсь с этим, так что это может быть мой ограниченный английский, но разве не наоборот? «привязка null3 к указателю»?

2. @idclev463035818: Вы можете сказать либо. Английский в этом смысле злой. Скорее похоже на C !

3. в этом случае я предпочитаю C

4. Как так? Литерал AFAIK 0 может использоваться как нулевой указатель для обратной совместимости в C , но не постоянная переменная int со значением 0 и не постоянное выражение int, например 1 — 1.

5. Правила для констант нулевого указателя были ужесточены в C 11; предыдущие версии допускали любое постоянное выражение rvalue значения 0, поэтому могут разрешать использование.