2016-07-01 3 views
2

엄격한 앨리어싱 경고를 제거하는 가장 쉬운 방법은 무엇입니까?c - 엄격한 앨리어싱 경고 처리 방법

코드는 :

uint8_t msg[3]; 
int retval; 

msg[0] = (uint8_t) INT_READ_EVENT; 
*((uint16_t *) &msg[1]) = bytesToRead; 

retval = write(intPipe[1], msg, sizeof(msg)); 

bytesToRead은 uint16_t 값으로 전달된다.

다른 끝에는 데이터를 처리하기 전에 이벤트 유형 (이 경우 INT_READ_EVENT)을 인식하는 단일 바이트를 수신하는 읽기가 있습니다.

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] 
    *((uint16_t *) &msg[1]) = bytesToRead; 
    ^

:

경고를 제거 할 수있는 빠르고 간단한 방법이 있습니까?

+1

endianess는 어떻게됩니까? 이식 가능한 코드를 원하지 않습니까? 비트 시프트 사용을 고려하십시오. – Lundin

+0

@Lundin 내가 틀렸다면 정정 해 주겠다.하지만 나는 엔디안에 대해 정말로 신경 쓸 것인가? 그냥 uint16_t로 보내고 나중에 uint16_t 값으로 받길 원합니다. 값이 내부적으로 저장되는 방법이 중요합니까? – Messut

+1

보낸 사람 컴퓨터는 endianess를 가지며 실제 프로토콜은 endianess를 가지며 수신기는 endianess를가집니다. 세 가지 중 하나가 다른 엔디안을 사용하면 걱정해야합니다. – Lundin

답변

1

char 버퍼를 사용하는 대신 구조체를 정의 할 수 있습니다.

struct message 
{ 
    uint8_t code; 
    uint16_t payload; 
}; 

struct message msg; 

msg.code = INT_READ_EVENT; 
msg.value = bytesToRead; 

멀티 플랫폼/이식성 코드에서 정렬 및 엔디안을 고려해야합니다.

또한 원시 당신이 할 수있는 모드로 구조체의 데이터에 액세스하려면 다음은 16 비트 값을 표현해야한다는 당신이 엔디안에 결정합니까 강제하기 때문에, 이와 같이

union message_with_raw 
{ 
    struct message msg; 
    uint8_t rawdata[sizeof(struct message)]; 
} 
+0

나는 서쪽에서 가장 빠른 총이다! (거의 동일한 답변을 게시했습니다 :)) – Lundin

+0

@ Lundin. 내가 첫 번째 부분, 당신은 노조 하나 +1을 얻었습니다. +1 – LPs

+0

그래서 DV는 당신에게 저에게 히트를 줄 수 있습니까 ????? – LPs

3

등 :

// Little-endian. 
msg[1] = bytesToRead & 0xff; 
msg[2] = (bytesToRead >> 8) & 0xff; 

빅 엔디안의 경우 오른쪽의 순서를 반대로하십시오.

3

당신이 프로토콜의 일종을 디코딩하는 것처럼 소리, 그래서 하나의 방법은 프로토콜 데이터에 대응하는 구조체 선언하는 것입니다 :

typedef struct 
{ 
    uint8_t something; 
    uint16_t bytes_to_read; 
} prot_data_t; 

그런 편의를 위해, 그리고 회피 앨리어싱 문제를, 당신은이를 넣을 수 있습니다

typedef union 
{ 
    prot_data_t named_data; 
    uint8_t  raw_data [sizeof(prot_data_t)]; 
} protocol_t; 

지금 당신은/전송 raw_data을 통해 바이트 데이터 바이트를받을 수 있지만 named_data을 통해 서로 다른 값에 액세스 할 수 있습니다 : 노동 조합이다. ,

이 코드뿐만 아니라 모든 솔루션 비트 이동을 사용하지 않는 것을 명심 엔디안에 의존 할 것이다 :


몇 가지 고려할 사항.

코드는 정렬 및 구조체/공용체 패딩 문제에 취약 할 수 있습니다. 최대한의 이식성을 위해 struct/union은 직렬화/직렬화 해제 루틴과 결합하지 않는 한 실제로 권장되지 않습니다.

+0

... 나는 또한 DV였다. 롤 ...? – LPs

+0

'struct' 패딩에 대해 언급 해 주셔서 감사합니다. GCC는 일부 컴파일러 관련 구문을 사용하여 정렬 된 메모리 위치 만 처리 할 수있는 CPU에서 어떻게 작동하는지 확신 할 수 없지만 GCC와 분명히 연결됩니다. – amn

2

경고는 이유가 있습니다. msg이 16 비트 경계에서 시작하면 msg[1]은 시작하지 않습니다. 따라서 해당 필드의 주소에서 시작하여 16 비트 값을 쓰려고하면 메모리에 잘못된 쓰기로 트랩을 트리거하여 충돌이 발생할 수 있습니다.

대신 한 번에 하나씩 바이트를 작성해야합니다.빅 엔디 언 형식 (네트워크 바이트 순서라고도 함)으로 바이트를 원한다고 가정하면 다음과 같이 수행합니다.

msg[1] = (uint8_t)(bytesToRead >> 8); 
msg[2] = (uint8_t)(bytesToRead); 
+0

이 "유효하지 않은 편지 쓰기"조건의 성격을 자세히 설명해 주시겠습니까? – amn

+0

@ amn 자세한 내용은 http://stackoverflow.com/questions/19352232/unaligned-memory-access를 참조하십시오. – dbush

관련 문제