2009-09-10 12 views
2

double ***const double ***으로 변환 할 수없는 이유는 무엇입니까? 당신의 C 태그가 믿을 수있는 경우다음 이유는 double ***에서 const double로 변환 오류가 발생합니다 ***

void foo(const double ***d) 
{ 


} 


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

     foo(d); 

} 
+0

에 C 및 C++로 태그가 지정된 질문이있는 경우 오류 란 무엇이고 허용되는 규칙은 혼란을 일으킬 수 있습니다. –

+0

@Pete 당신 말이 맞아요. 이 예제에서는 usigng C 컴파일러입니다. 이와 관련하여 규칙이 정말로 다른가요? – vehomzzz

답변

8

는, GCC는 유형이 당신의 예와 const double * const * const * d 모두 다르기 때문에 경고를 생성합니다. C++에서는 OP 코드에 오류가 있지만 slap-const-everywhere 방식이 적합합니다.

컴파일러가 경고하는 이유는 포인터 (또는 추가 간접 참조)에 대한 포인터가 매개 변수가 가리키는 위치를 수정하여 호출자에게 포인터를 반환 할 수있게한다는 것입니다.

포인터의 대상이 const로 선언 된 경우 호출 된 함수는 반환 할 때 const로 처리되도록 값을 예상합니다.

이 에러가 될 이유 나타내는 const T**T**를 전달하는 간단한 경우 : C

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++ 객체의 변경 가능한 데이터가 변경 될 수 있습니다. AC 컴파일러는 코드를 최적화하여 const 데이터를 어딘가에 캐시 할 수 있지만 C++ 컴파일러는 가능한 mutablity 때문에 그렇게 할 수 없으므로 위와 같이 const가 아닌 데이터로 const 데이터를 반환 할 수 없다는 약한 제약이 있습니다. . 따라서 C++에서 double***const이 수정 불가능한 메모리의 반환을 막기 때문에 const double * const * const * d으로 캐스팅 될 수 있지만 컴파일러가 메모리에 반복적으로 액세스하는 것을 최적화하면 C에서 경고 및 가능한 오류가 발생합니다.

0
+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 자체 또는 블랙 박스에 const를 추가 할 수 있지만 블랙 박스의 내용은 추가 할 수 없습니다. 그래서

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

은 *** D D의 값만 CONST이다. (또는 상기 간접) B ** 더블 더블 B에 CONST에서 변환되지 않은 상태에서 C 이중에서 CONST로 전환 이중 *는 법적이다. 따라서

는 변환하는 더블 *** D const를 이중 *** D2 다음을 수행 할 수 : 물론

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

더블 const를 *** D의 사용 non-const 우회로 때문에 의심스러운 채로 남아있다.

관련 문제