2011-10-07 5 views
3

다음 코드 조각이 있습니다.호환되지 않는 포인터 유형 (const vs non-const)에서 반환. C/GCC

typedef uint8_t array_t[8]; 
static array_t _my_array; 
static const array_t * foo(void) { 
    return &_my_array; // <-- return from incompatible pointer type 
} 

어떻게이 오류를 수정합니까? 내가 뭘 잘못하고 있죠?
_my_array를 (const array_t *)로 캐스트해야합니까? 포인터에서 암시 적으로 const 포인터로 캐스트하지 않아야합니까?

참고 :

return _my_array; 

은로 잘 작동합니다. 즉, 같은 경고로 컴파일됩니다.

+1

이것은 사용자의 문제와 관련이 없지만 식별자 '_my_array'의 사용은 좋지 않습니다. C99 7.1.3 : "밑줄로 시작하는 모든 식별자는 항상 일반 및 태그 이름 공간에서 파일 범위가있는 식별자로 사용하도록 예약되어 있습니다." –

+0

은 static array_t _my_array 파일 범위가 아닙니다. –

+2

네, 그게 문제입니다. 이러한 식별자는 구현 *에 예약되어 있습니다. 자신을 사용할 수 없습니다. 동일한 섹션의 뒷부분에서 : "프로그램이 예약 된 컨텍스트에서 식별자를 선언하거나 정의하면 [...] 동작이 정의되지 않았습니다." 구현 (컴파일러 또는 미리 정의 된 헤더)은 "_my_array"라는 자체 파일 범위 엔티티를 선언 할 수 있습니다. 최신 C99 초안은 [here] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf)입니다. –

답변

2

문제는 const입니다. 함수는 const array_t * (const array_t에 대한 포인터)을 반환하지만 반환되는 표현식 &_my_arrayarray_t *이며 두 유형은 호환되지 않습니다.

typedef uint8_t array_t[8]; 
static array_t _my_array; 
static array_t * foo(void) { 
    return &_my_array; 
} 

편집 :

간단한 수정 반환 형식에서 const을 드롭하는 것입니다

내가 컴파일러의 버그를 제안 주저 해요,하지만 난 함께 왔어요 내가 생각하는 테스트 프로그램은 gcc의 버그 또는 C 표준의 매우 모호한 부분을 나타냅니다.

typedef int this_type; 
typedef int that_type[8]; 

static this_type this; 
static that_type that; 

static const this_type *this_func(void) { 
    return &this; 
} 

static const that_type *that_func(void) { 
    return &that; 
} 

나는 이것을 컴파일

gcc -c -std=c99 -pedantic-errors c.c (GCC 4.5.2), 내가 얻을 :

c.c: In function ‘that_func’: 
c.c:12:5: error: return from incompatible pointer type 

이 왜 const that_type*that_type*에서 암시 적 변환에 대해 불평 않지만, this_type*에서하지에 대한 변환 const this_type*. that_type 이후

가 타입 정의 , 그것은 배열 형 별칭, 그리고 that_type* 배열 (되지 배열의 요소에 대한 포인터)에 대한 포인터; 내가 말할 수있는 한 배열에서 포인터로의 변환은 없다. 나는 그렇지 않다 this_type이 정수형이고 that_type이 배열 형식 인 것이 차이를 만들어야한다는 것을 생각한다.

다른 데이터 요소 : Solaris 9의 경우 cc -c -Xc c.c은 불만하지 않습니다.

foo 포인터를 const foo에 대한 포인터로 변환하는 것이 안전해야합니다. const-correctness를 위반할 기회는 없습니다.

내가 옳다 경우, 해당 코드가 유효 GCC의 경고는 잘못된 것입니다, 당신은 함수 정의에 const 놓아 그 중 하나를 해결할 수 있습니다 (이 const array_t*보다는 array_t*를 반환 할, 또는로 return 문에 캐스트를 추가합니다.

return (const array_t*)&_my_array; 

내가 잘못하면 곧 누군가를 가리킬 것으로 예상됩니다.

(.. 식별자가 다소 고의적으로 this하는 C++ 키워드의 내 사용, 이것은 내가 C++이 지역에서 약간 다른 규칙이 있음을 이해할 C의 질문입니다.)

EDIT2 : I 방금 gcc bug report을 제출했습니다.

EDIT3 : 조셉 S. 마이어스 내 버그 보고서에 응답 :

이것은 버그가 아닙니다. 암시 적으로 "int에 대한 포인터"는 "const int에 대한 포인터"로 변환 될 수 있지만 "int 배열"에 대한 포인터 " "(6.5.16.1 참조) 및 "const that_type *" "const int의 배열에 대한 포인터"입니다 (" const int 배열"에 대한 포인터는 이러한 형식이 아니며, 이러한 변환은 변환의 허용 된 대상입니다 (6.7.3 # 8 참조).

+0

clang도 만족스럽지 않습니다. '경고 : 결과 유형이'that_type const * '(일명'int const (*) [8] ') 인 함수에서'that_type * '(일명'int (*) [8] ')을 반환하는 호환되지 않는 포인터 유형' – nos

+0

I crang이 gcc와 호환되도록 시도한다고 생각하십시오. 그들은 단지이 버그를 재생했을 가능성이 있습니다. gcc 관리자가 내 버그 보고서에 어떻게 반응하는지 보겠습니다. –

+0

@Keith. Joseph의 답변을 인용 한 다음 게시 할 수 있습니다. –

1

Answered by Joseph S. Myers

이것은 버그가 아닙니다. 암시 적으로 "int에 대한 포인터"는 "const int에 대한 포인터"로 변환 될 수 있지만 "int 배열"에 대한 포인터 " "(6.5.16.1 참조) 및 "const that_type *" "const int의 배열에 대한 포인터"입니다 (" const int 배열"에 대한 포인터는 이러한 형식이 아니며, 이러한 변환은 변환의 허용 된 대상입니다 (6.7.3 # 8 참조).

관련 문제