2013-04-01 2 views
17

최근에 엄격한 앨리어싱 규칙이 적용되었지만 void *을 사용하여 규칙을 위반하지 않고 유형을 수행하는 방법을 이해하는 데 문제가 있습니다.C99에서 엄격한 앨리어싱 규칙을 위반하지 않고 void *로 입력하십시오.

나는이 규칙 나누기 알고

int x = 0xDEADBEEF; 

short *y = (short *)&x; 
*y = 42; 

int z = x; 

을 그리고 나는 안전하게 유형 말장난에 대한 C99의 조합을 사용할 수 있다는 것을 알고 :

union{ 
    int x; 
    short y; 
} data; 

data.x = 0xDEADBEEF; 
data.y = 42; 

int z = data.x; 

하지만 어떻게 안전하게 void *에 사용합니까 C99에서 유형 - 실행을 수행 하시겠습니까? 올바른 다음과 같다 :

int x = 0xDEADBEEF; 

void * helper = (void *)&x; 

short *y = (short *)helper; 
*y = 42; 

int z = x; 

내가 그 코드는 여전히 변수 x의 주소의 메모리부터 엄격한 앨리어싱 규칙을 깰 것 생각하는 것은 모두 x와 역 참조 y에 의해 변경 될 수 있습니다.

형식 지정이 void *을 통해 정의되지 않은 경우 C99에서 void *의 목적은 무엇입니까?

답변

19

void *은 유형 펀치와 아무 관련이 없습니다. 주요 목적은 다음과 같습니다

  1. 는 일반 할당 및 발신자가 (예를 들어, mallocfree)를 저장하고있는 객체의 유형에 대한 상관 없어 작업을 자유롭게 허용하기 위해.

  2. 발신자가 콜백 (예 : qsortpthread_create)을 통해 다시 전달할 함수를 통해 임의의 유형에 대한 포인터를 전달할 수 있도록 허용합니다. 이 경우 컴파일러는 유형 검사를 시행 할 수 없습니다. 콜백이 올바른 유형의 객체에 액세스하도록 콜러와 콜백을 작성할 때 책임자 인입니다. void

포인터는 실제 객체 포개어 unsigned char [] 표현으로 객체상에서 동작 몇 군데 (memcpy 등)에 사용된다. 이는 유형 펀칭으로 볼 수 있지만, char 유형의 표현에 액세스하기 위해 별칭을 지정할 수 있으므로 별칭 위반이 아닙니다. 이 경우 unsigned char *도 작동하지만 void *은 포인터가 자동으로 void *으로 변환된다는 장점이 있습니다.

예에서 원래 유형은 int이며 공용체가 아니기 때문에 입력 할 수있는 합법적 인 방법은 없습니다 (short). 대신에 x의 값을 공용체에 복사하고 거기에서 잘 정의 된 유형 - 실행을 수행 한 다음 다시 복사 할 수 있습니다. 좋은 컴파일러는 사본 전체를 생략해야합니다. 또는 쓰기를 char 글으로 긋고 합법적 인 앨리어싱이 될 수 있습니다.

+5

오오알이 보입니다. 그래서'void * '가 사용되는 경우 프로그래머는 형변환을위한 올바른 타입을 이미 알고 있어야합니다. 원래의 데이터 유형 (즉,'int *'->'void *'->'int *')이 사용되기 때문에 아무런 형벌도 발생하지 않습니다. –

+1

네, 그렇습니다. +1 –

+1

내가 틀릴 수도 있지만,'unsigned char'가 아닌 별명을 지정할 수있는'char'만이 아닌가? – Arnout

관련 문제