#c
#c
Вопрос:
Может кто-нибудь объяснить, почему второе преобразование разрешено, а первое — нет? Они оба потенциально позволяют изменять постоянное значение lvalue…
double *wPtr;
const double ** wRef = amp;wPtr;
const double * const * wRef = amp;wPtr;
Спасибо,
регулярное
Добавлена ошибка компиляции из Comeau…
int main( int argc, const char* argv[] )
{
double *wPtr;
const double ** wRef = amp;wPtr;
return 0;
}
Compiling Comeau C/C 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C C 0x_extensions
"ComeauTest.c", line 4: error: a value of type "double **" cannot be used to
initialize an entity of type "const double **"
const double ** wRef = amp;wPtr;
^
1 error detected in the compilation of "ComeauTest.c".
Комментарии:
1. Не могли бы вы опубликовать пример сообщения об ошибке, которое вы получаете при компиляции этого кода? Я думаю, что может происходить что-то еще…
2. @antonm: Нет, он прав в том, что первое представляет собой явную ошибку, обнаруженную компилятором, а второе — нет. Он просто не совсем правильно понимает значение второго.
3. @Nicholas: да, теперь я это понимаю. Кто-то (вы?) был опубликован ответ, который я больше не вижу. В нем была эта полезная ссылка: parashift.com/c -faq-lite/const-correctness.html#faq-18.17
4. @antonm: Я удалил это, когда исправлял. Я только что проснулся и перепутал объяснение. 🙂 Теперь это вернулось.
5. Эта ссылка больше не работает, так что вот она снова: isocpp.org/wiki/faq/const-correctness#constptrptr-conversion
Ответ №1:
Потому что второй пример не допускает модификацию const lvalue (по крайней мере, не без реальных усилий с вашей стороны (приведение, которое само по себе часто является признаком опасности)). Я не уверен, почему вы думаете, что это так, поскольку вы не предоставляете дополнительных объяснений..
const double * const * wRef = amp;wPtr;
Вы должны прочитать это очень внимательно. В нем говорится: «wRef — это указатель на постоянный указатель на double, который является const».
Вы можете изменить wRef (чтобы указывать на другой объект). Вы не можете изменить значение, на которое оно указывает (указатель wPtr), и вы не можете изменить значение, на которое указывает wPtr. Это не предоставляет (обычного) способа изменения значения const lvalue .
Первый пример, конечно, явно опасен и запрещен, как вы и ожидаете.
Кстати, вам следует прочитать главу о корректности C в C FAQ, если вы еще этого не сделали. Раздел 17 рассматривает этот конкретный случай, хотя в основном с точки зрения того, почему первое не разрешено, и явно не пытается описать, почему разрешено второе.
Комментарии:
1. Спасибо, ваш ответ и ссылка на часто задаваемые вопросы по c прояснили ситуацию. Я смотрел на проблему под неправильным углом.
Ответ №2:
Таким образом, наличие слова ‘const’ слева от слова довольно вводит в заблуждение.
Ваше второе утверждение было бы лучше сформулировано как double const * *wRef = amp;wPtr
По сути, это указатель на указатель на const double . Здесь вы можете изменить значение lvalue, потому что оно не является const — const является только значение double, на которое указывается.
Второй является double const * const * wRef
— т.е. указатель на константу указывает на константу double.
Сам указатель на указатель может быть изменен, но значение double, на которое он затем указывает, должно быть const . Вы не можете изменить их значение const lvalue.