2009-09-10 2 views
2

Почему он не может преобразовать double *** в const double ***?Зачем мне нужна ошибка преобразования от double *** до const double ***

void foo(const double ***d) 
{ 


} 


int main (int args, char*[] args) 
{ 
     double ***d; 
     /*initialize d */ 

     foo(d); 

} 
+0

, имеющий вопрос с тегами как с C, так и с C++, когда правила относительно того, что является ошибкой и что допускается, различаются, создает некоторую путаницу. –

+0

@ Пойди, ты прав. Я - компилятор usigng C для этого примера. Действительно ли правила в этом отношении разные? – vehomzzz

ответ

8

Если C тег можно верить, НКУ генерирует предупреждение, как типы различаются как для вашего примера и const double * const * const * d. В C++ это ошибка в коде OP, но подход slap-const-all является законным.

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

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

Более простой случай прохождения T** к const T**, который иллюстрирует, почему это ошибка будет:

void foo (const char ** z) 
{ 
    *z = "A"; 
} 


int main (int nargs, char** argv) 
{ 
    char* z = 0; 
    char** d = &z; 

    // warning in C, error in C++ 
    foo (d); 

    // bad - modifies const data 
    z[0] = 'Q'; 
} 

const в C означает, что данные не изменится. const в C++ означает, что данные не будут меняться публично - изменчивые данные в объекте C++ могут измениться. Компилятор AC мог бы оптимизировать свой код, чтобы он кэшировал некоторые из данных const где-то, но компилятор C++ не может этого сделать из-за возможной мутабельности, поэтому имеет более слабое ограничение, что вы не можете вернуть данные const неконстантным, как указано выше , Таким образом, в C++ double*** может быть отлит до const double * const * const * d, поскольку дополнительные const предотвращают возврат немодифицируемой памяти, но в C он генерирует предупреждение и возможные ошибки, если компилятор оптимизирует повторный доступ к памяти в другом месте.

0

использование const_cast_operator()

+0

это C++, вопрос был о C – fortran

+0

@fortran, вопрос был первоначально помечен как C и C++. Сам вопрос не дал понять, какой язык используется, поэтому сочетание ответов на C и C++ – Glen

0

Это также верно для ** (указатель на указатель) по одинаковым причинам.

Этот код также производит эту ошибку, и это яснее понять, почему компилятор не позволит вам сделать это здесь:

double d = 0.0; 
    double * pd = &d; 
    const double ** ppd = &pd; // <--- Error 

Если бы вы были в состоянии сделать это, вы могли бы иметь «Const» указатель на данные (ppd), которые вы можете изменить, изменив изменяемое значение d. Это нарушает const, поэтому компилятор не позволит вам это сделать.

+1

Это не причина, потому что это законно: double d = 0; double const * pd = & d ;, что также позволяет вам изменить «const» pointee, изменив локальную переменную. – me22

0

Рассмотрите d указатель на черный ящик.

Компилятор может добавлять константу либо к d, либо к черному ящику, но не к содержимому черного ящика. Так

void foo1(double ***d);  /* ok, no casts needed */ 
void foo2(double *** const d); /* ok, no casts needed; const added to `d` itself */ 
void foo3(double ** const *d); /* ok, no casts needed; const added to the blackbox */ 
void foo4(double * const **d); /* oops, trying to change the insides of the blackbox */ 
void foo5(const double ***d); /* oops, trying to change the insides of the blackbox */ 
void foo6(double ** const * const d); 
/* ok: d is a constant pointer to a constant blackbox */ 
0

С сопзом двойной *** д только значением д является Const.В C преобразование из двойного к сопзу двойного * а является законным в то время как преобразование из двойных б к сопзу двойной ** б (или дополнительной косвенности) не является.

Поэтому для преобразования из двойных *** d к сопзу двойной *** d2 вы можете сделать следующее:

 
    double*** d; 
    const double* b = **d; 
    const double** c = &b; 
    const double*** d2 = &c; 

Конечно использование сопза двойной *** d остается сомнительным из-за неконстантных ограничений.

Смежные вопросы