2016-09-29 1 views
3

나는이 큰 오픈 소스 C 라이브러리와 함께 일하고 있어요, 나는 자주 같이 유형 간의 캐스트 찾을 :이런 캐스트를 할 이유가 있습니까?

char *str; 
//some code 
unsigned char *str2 = *(unsigned char **) &str; 

내가 그것으로 주위를 연주하고, 나는 그것을 변경하는 경우

처럼 보이기를
unsigned char *str2 = (unsigned char *) str; 

문제없이 작동하는 것처럼 보입니다. 이러한 캐스트는 코드 전체에서 자주 사용되며 unsigned char 이외의 여러 유형에서 사용됩니다.

참조 및 참조 해제를 통해 이처럼 캐스트 할 이유가 있습니까?

편집 : 관련성이 있는지는 모르지만이 코드는 C89와 호환되어야합니다.

편집 2 :에서 찾을 몇 가지 구체적인 예

void *q = *(void **)(&p[i]); 

: 발견 draw-paint.c (라인 332)

return cbz_strnatcmp(*(const char **)a, *(const char **)b); 
//both parameters are expected to be const char* 

: memento.c (라인 1122)

unsigned int rgba = *((unsigned int *)color); 

에서 확인할 에서 : mucbz.c (라인 73)

+2

라이브러리 이름을 지정할 수 있습니까? – 2501

+0

@ 2501 [mupdf] (http://mupdf.com/) – Cody

+1

실제 소스 코드에 그러한 예제에 대한 링크를 게시 할 수 있습니까? – 2501

답변

3

제시된 두 가지 대안은 한 유형의 포인터를 형변환을 통해 다른 포인터 유형으로 변환하는 것입니다. 이것은 C89를 포함하여 허용됩니다. 원래 코드에서 변환 된 포인터는 명시 적으로 참조 해제됩니다. 개정 된 코드에서 포인터는 다른 곳에서 참조 해제된다고 가정해야한다. 이와 관련하여 두 변형은 정확히 동일한 종류의 (허용 된) 동작을 수행합니다.

하지만, 하나 개의 기술적 차이점이있다 : str2 할당로서 초기화 식의 값이 너무 판독 될 때 첫 번째 대안 형 unsigned char *의 좌변을 통해 액세스되는 유형 char * 값을 야기한다. 이 두 가지는 표준 용어의 의미에서 "호환 가능한 유형"이 아니며, 후자는 전자에 해당하는 부호없는 유형 (포인터 자체는 부호가 없음)이거나 후자는 문자 유형 또는 다르게 규정 된 버전입니다 전자, 또는 노동 조합 유형. 따라서 접근은 구어체로 "엄격한 앨리어싱 규칙"이라고 알려진 표준 규정을 위반합니다.

두 번째 대안은 호환되지 않는 포인터 유형을 변환하지만 문자 유형이 별칭을 지정할 수 있기 때문에 엄격한 별칭 규칙에서 허용하는 후속 액세스 (첫 번째 대안도 제공)는 허용됩니다. unsigned charchar에 해당하는 부호없는 유형이며 이러한 해당 유형 간의 별명 지정이 허용됩니다.

실제로는 프로덕션 준비가 된 컴파일러가 예상했던 것 외에는 원래 코드로 수행 할 가능성은 거의 없지만 수정 된 코드는보다 명확하고 정확합니다.

+1

'char **'타입을'unsigned char ** '로 캐스트하는 것은 엄격한 앨리어스 위반이다. 서명이 엄격한 앨리어싱에 대해 중요하지 않다는 생각이 들었습니다. – yano

+1

@yano, 캐스트 자체는 위반 사항이 아니며 서명 여부는 * 직접 * 문제가 아닙니다. 그 위반은'* (unsigned char **) & str'의 값이 접근 될 때 나온다. 왜냐하면 그 표현식은'unsigned char * '타입의 lvalue이고 실제로 그것이 지정하는 객체의 유효 타입은'char *'이다. 문자 유형은 별칭을 지정할 수 있지만 문자 유형이 아니기 때문에 호환되지 않는 포인터 유형입니다. 또한, 어느 쪽도 상대와 일치하는 부호 첨부 형 또는 부호 없음 형태도 허용되지 않습니다. –

+0

약 10 번 더 읽어야합니다 .. 감사합니다. – yano

2

이렇게 캐스팅 할 이유가 없습니다. 선택의 문제.

unsigned char *str2 = *(unsigned char **) &str; 

의 경우 s 포인트 문자의 주소를 얻기 위해 불필요한 역 참조있다.

unsigned char *str2 = (unsigned char *)str; 

를 사용

나에게 깨끗한 보인다.

+1

첫 번째 것은 정의되지 않은 동작입니다 (John Bollinger의 답변에 설명되어 있음) –

+0

@ M.M Thanks. 전에는 몰랐습니다. 이 대답을 삭제합니다. – haccks

관련 문제