2013-06-27 2 views
4

내가 C에서 이런 짓을 한 횟수의, 오래 전, 카운트를 분실했습니다C에서 메모리를 재 해석하는 올바른 방법은 무엇입니까?

struct foo f; 
struct foo* pf = &f; 
char* pc = (char*) pf; 
transmit(pc, sizeof(f)); 

아니면 :

char* buffer[1024]; 
receive(buffer, 1024); 
float values[256]; 
for(int ii = 0; ii < 256; ii++) { 
    float* pf = (float*)(buffer + ii*4); 
    values[ii] = *pf; 
} 

아니면 :

uint32_t ipAddress = ...; 
uint8_t* p = (uint8_t*)&ipAddress; 
uint8_t octets[4] = {p[0], p[1], p[2], p[3]}; 
printf("%d.%d.%d.%d\n", octets[0], octets[1], octets[2], octets[3]); 

다른 포인터 유형으로 캐스팅하여 이런 식으로 메모리를 재 해석하면 정의되지 않은 동작이 호출된다는 것을 발견했습니다. 그리고 위의 모든 예는 절대적으로 필요한 것입니다. 그것들을하는 올바른 방법은 무엇입니까?

+1

당신은'union' 키워드에 관심을 갖게 될까요? – Christoph

+0

개인적으로, 노동 조합을 사용하는 것은 typecast보다 이러한 문제에 대한 훨씬 나쁜 해결책이라고 생각합니다. 더 많은 코드를 작성하고, 더 이상한 유형을 만들고, 여전히 * 모든 곳에서 캐스팅해야합니다. –

+0

@CarlNorum : 타겟 타입이'char'가 아닌 경우 포인터를 캐스팅하면 UB가됩니다. 효과적인 타이핑 규칙은 기본적으로 C를 유형 정보가 메모리 위치 자체에 바인딩되는 강력한 유형 언어로 만듭니다. 그러나 형식 시스템은 컴파일러가 잘못 입력 된 표현식을 통해 메모리에 액세스하려고 시도 할 때 매우 불건전하지만 실제로 이러한 불변량이 더 높은 최적화 수준을 유지한다고 가정 할 수 있습니다 (예 : 'strict-aliasing'의 경우) – Christoph

답변

5

char * (또는 unsigned char * 또는 그 typedefs) 로의 캐스팅은 특수한 경우이며 이 아닌은 정의되지 않은 동작을 일으 킵니다. 는 C 규격에서

, 포인터, 제 7 6.3.2.3 : 오브젝트 포인터가 캐릭터 타입에 대한 포인터로 변환된다

, 최저의 결과 포인트의 바이트를 어드레싱 그 물체. 객체의 크기까지 결과를 연속적으로 증가 시키면 객체의 나머지 바이트에 대한 포인터가 생성됩니다.

첫 번째 & 사례는이 사례에서 다룹니다. 두 번째 예제는 조금 엉뚱한 것이지만 대부분의 시스템에서 작동 할 것입니다. 당신이 정말 일을해야하는 것은 다음 중 하나입니다 values에 직접 읽기 :

float values[256]; 
receive(values, sizeof values); // assuming receive() takes a "void *" parameter 

또는 같은 것을하는 것은 (정렬 문제를 방지하기 위해) :

char buffer[1024]; 
receive(buffer, sizeof buffer); 
float values[256]; 
for(int i = 0; i < 256; i++) 
{ 
    char *pf = (char *)&values[i]; 
    memcpy(pf, buffer + i * sizeof(float), sizeof(float)); 
} 

(나는 char 배열로 buffer을 변경합니다 - 그 질문에 오타가 있다고 가정합니다.)

+0

링크를 제공 할 수 있습니까? 내 K & R C 서적은 그다지 말하지 않지만 ... 다시 ISO 또는 ANSI C가 아닙니다. – Mgetz

+2

확실히 : [C11 (PDF 링크)] (http://www.open-std.org/jtc1/sc22/wg14 /www/docs/n1570.pdf) 또는 [C99 (PDF link)] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf)를 선택하십시오. –

+0

저는 C를 처음 접했고'char * pf = (char *) & float [i];'에 대해서 궁금해했습니다. 정확히 여기'char *'에 주조하고 있습니까? (필자의 컴파일러는''float '을하기 전에 구문 분석 오류가 발생합니다.) – qwwqwwq

관련 문제