2009-09-23 4 views
2

, 나는 아래의 코드 라인 4에 다음과 같은 경고를 얻을 :"const int ** const"와 "int **"유형 사이의 초기화가 허용되지 않습니다. 이유가 무엇입니까? 뇌파 업 정보 (ALL)를 사용하여 경고와 함께 V1.8의 z/OS의 XL C 컴파일러를 사용하여

WARNING CCN3196 Initialization between types "const int** const" and "int**" 
       is not allowed. 


1 int foo = 0; 
2 int *ptr = &foo; 

3 const int * const fixed_readonly_ptr = ptr; 

4 const int ** const fixed_ptr_to_readonly_ptr = &ptr; 

나는 쌀 수 없습니다 내 왜 내가이 경고를 받고 있는지 주위에 머리를 숙이다. const int (3 행)에 대한 const 포인터에 int 포인터를 할당 할 수 있다면 const 포인터에 대한 int 포인터의 주소를 const int에 대한 포인터에 할당 할 수없는 이유는 무엇입니까? 내가 뭘 놓치고 있니?

위의 코드는 소량의 코드에서 발생하는 문제를 보여주는 간단한 예제입니다. 실제 문맥은 struct (struct s ** const)에 대한 포인터에 대한 const 포인터를 가지고 있으며이 포인터를 const 포인터 (const struct s **)에 대한 const 포인터로 정의 된 함수의 인수로 전달하는 것입니다. const). 이것은 함수가 구조체 (따라서 첫 번째 const)의 데이터를 수정하지 않고 전달 된 주소 (즉 두 번째 const)를 항상 보유하는 포인터 매개 변수를 수정하지 않기 때문입니다. 가리키는 포인터의 값은 그 방법으로 변경 될 수 있습니다 (따라서 ** 사이에 세 번째 const가 없음).

+0

파벨 (Pavel)과 찰스 (Charles)는 컴파일러가 경고하는 이유를 완벽하게 분명히했습니다. 나는 둘 다 upvoted지만 C의 관점에서 (두 답변은 매우 유사하고 왜 경고가 발급되었는지 보여 주지만) 그것을 부셔 찰스에게 크레딧을 줬다. –

답변

3

는 C 규칙은 당신이 뭔가에 대한 포인터를 변환 할 수 있다는 것입니다 const 무언가에 대한 포인터에 연결하지만, 무언가는 const와 휘발성 자격을 포함하여 정확히 같은 유형이어야한다.

이 규칙에 대한 근거는이 두 라인의 두 번째이 허용 된 경우이다 :

int *ptr; 

const int ** const fixed_ptr_to_readonly_ptr = &ptr; 

다음이가 캐스팅없이 유형의 안전을 파괴하는 데 사용할 수 있습니다.

const int i = 4; 

// OK, both sides have type const int * 
*fixed_ptr_to_readonly_ptr = &i; 

// the value of fixed_ptr_to_readonly_ptr is still &ptr 
// the value of ptr is now &i; 

*ptr = 5; 

// oops, attempt to change the value of i which is const 
5

유형 안전 위반입니다. (나는 분명히이 포인터 또는 pointee에 적용되는지 여부를 확인하기 위해 비트 주위에 const을 단행하지만, 의미는 똑같은 일을 의미)이 코드를 고려해

int* p = 0; 
int const** pp = &p; // presumably ok 

int const c = 123; 
*pp = &c; // okay, &c is int const*, and *p is int const* lvalue 

*p = 666; // okay, *p is int lvalue 

// wait, so we just changed the value of (const) c above, with no const_cast!