Поскажите чем мотивирована ошибка компиляции сл. кода (VC++): Код (Text): { int **ppi; const int **ppci; ppci = ppi; // error C2440: '=' : cannot convert from 'int **' to 'const int **' // Conversion loses qualifiers} } Т.е. почему считается, что это преобразование "loses qualifiers" ?
green int** и const int** - разные типы, потому и ошибка. Точно так же как если написать например int* и unsigned int*. Или вопрос был почему именно так сформулированно сообщение об ошибке? Кстати C-компилятор из MS Visual Studio компилирует пример без ошибок. Ошибку выдает компилятор C++.
Мне непонятно, почему компилятор считает, что преобразование Код (Text): int** -> const int** недопустимо. Ведь в таком случае Код (Text): int *pi; const int *pci = pi; никаких ошибок не возникает.
Да, прошу прощения, забыл плюсы с названии топика. Кстати, это очень странно и похоже на баг в MS C-компиляторе - другой компилятор выдает в этом коде ошибку как в C так и в C++ режимах.
green Потому что здесь приравнивание происходит на стадии инициализации. Все равно что написать скажем: int a=0xFFFFFFFF; unsigned int b=0xFFFFFFFF; Тоже проблем не будет, хотя интерпретируется число 0xFFFFFFFF в результате по разному.
Зато вот такое компилируется без ошибки: int c=1; const int* const cc=&c; const int* const *ppc=&cc; int**p; ppc=pp; Видимо внутри VC++ интерпретирует const int** как const int* const *. Баг компилятора? P.S.: Посмотрел, труп страуса пишет, что T* должно всегда без ошибки приводится к const T*, про двойные указатели не пишет ничего. Может это implementation specific?
Stiver Тьфу! Как раз не интерпретирует. Так что это не баг, а действительно просто разные типы: int** - это указатель на (int*) const int** - это указатель на (const int*) и друг к другу они по умолчанию не приводятся.
Stiver Но ведь в этом случае Код (Text): int **ppi; const int * const *ppci; ppci = ppi; типы тем более разные, но тем не менее компилируется без ошибок. И странно, что компилятор MS выдает ошибку в C++ но не в C-режиме, а Comeau ругается в обоих режимах. Похоже на багу в компилере MS, т.к. никакой С++-специфики в таком коде вроде нет. Вопрос больше академический, но всё же интересно...
green В этом случае действует правило, которое я процитировал выше: т.е. int** => int* const* => const int* const* Привести int** к const int** с помощью этого(да и любого другого) правила невозможно. P.S.: Какой из C-компиляторов прав не знаю, нужно действительно в спецификации смотреть. Может в Comeau не ANSI C a например ISO?
гм... насколько я понял, Вы полагаете, что компилятор выполняет преобразование поэтапно, на каждом уровне dereferencing: (int**) => (int*) const* => (const int)* const* но в таком случае, учитывая также очевидное правило T* -> T*, получается (int**) => (int*)* => (const int)* * Или я туплю ?
R_NEW не, const мне не враг если использовать C-подобные приведение типов, то предохраняющие ф-ци const сводятся на нет. практически это не представляет проблемы, мне просто хотелось понять логику компилятора.
green Если я правильно понимаю, компилятор проходит цепочку только один раз сверху вниз. На первом шаге получает (int*)* и (const int*)* и смотрит, можно ли с помошью правил T*->const T*, T*->void* и т.д. их приравнять. Если нет, то вылетает с ошибкой, а не проверяет рекурсивно дальше. Поэтому например void** v; int** i; v=i; тоже дает ошибку, хотя казалось бы int** => (int*)* => (void*)* => void** не надо меня пожалуйста на Вы обзывать
нда... ладно, может так и есть, но если решение о допустимости преобразования принимается после dereferencing 1-го уровня тогда таких "правил" немало должно быть... Типа умом компилер не понять Спасибо. договорились PS кстати никто не знает как по-русски будет dereference pointer ? Lingvo говорит "разыменовывать", но похоже это не то
Вот здесь еще один вариант ответа: http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17 Правда если его принять, то остается непонятным, почему int** не приводится к void**. Так что моя версия мне нравится больше