2017-02-21 5 views
0

상상해보십시오! 일부 집 자동화를 처리하는 IO 인터페이스에서 uint8_t data[8]으로 8 바이트를받습니다. 이 8 바이트는 휴한지로 해석해야합니다어떻게 매핑 된 메모리의 비트에 액세스합니까?

Memory interpretion

가 어떻게 올바른 비트 액세스합니까? 는 지금 생각에 대한 두 가지 솔루션 :

해결 방법 1 :

struct data_s { 
    uint8_t LightSwitch0:1; 
    uint8_t LightSwitch1:1; 
    uint8_t LightSwitch2:1; 
    uint8_t LightSwitch3:1; 
    uint8_t Brightness:4; 
    uint8_t Dimmer0; 
    uint8_t Dimmer1; 
    uint8_t Dimmer2; 
    uint8_t Dimmer3; 
    uint8_t Dimmer4; 
    uint8_t DoorSwitch:1; 
    uint8_t Spare:7; 
} 

다음으로 할 수 단순히 캐스트 않으며, 본 실시 예에 따라 구조체의 멤버에 액세스 :

일부 비트 필드와 구조체 정의
data_s *foo = data; 
foo->LightSwtich1 = FALSE; 
foo->Brightness = 7; 
//... 

해결 방법 2 : 비트 마스크 :

data[0] |= 0x02; 
data[0] = (data[0] & 0x0F) | ((7 << 4) & 0xF0) 
//... 

글쎄, bitfields 컴파일러에 의존하고 그 휴대용되지 않습니다 알아요. 솔루션 2가 종종 선호되는 이유입니다. 그럼에도 불구하고 솔루션 2는 훨씬 더 복잡해 보이고 읽을 수 없습니다. 매핑 된 메모리가 8 바이트 이상이면 더 많은 작업이 필요합니다.

정말 해결책 2가 필요합니까? 아니면 #pragma reverse_bitfields on 지시어를 사용하여 솔루션 1의 이식성을 향상시킬 수 있습니까? 코드가 교차 컴파일러가있는 하나의 대상에 대해서만 빌드되는 경우 솔루션 1을 사용할 수 있습니까?

내 질문은 : 올바른 비트를 어떻게 액세스해야합니까?

+0

비트 필드는 휴대용이며 C 표준의 일부입니다. 그것은 코드 가독성과 습관의 문제입니다 : 제 경우에는 비트 마스크를 선호하지만 많은 사람들이 비트 파일을 선호합니다. – LPs

+0

MISRA가 비트 필드의 사용을 금지하는 데 사용되었지만 여전히 사용되는지는 알 수 없습니다. – Toby

+0

#define 매크로를 사용하여 솔루션 2를 훨씬 쉽게 읽을 수있게 만들 수 있습니다. 장래에 변경 작업을하는 데 필요한 작업량을 줄이는 이점이있는 단 한 곳에서만 읽을 수없는 추악한 것들을 완성하게 될 것입니다. –

답변

3

비트 필드가 컴파일러에 종속되는 정도는 다소 과장되어 있습니다. 이상한 방법으로 사용하면 이상하게 생깁니다.

예에서 모든 필드는 서명이없고 같은 저장 유형을 가지고 있으며 저장 영역 경계를 넘지 않으며 사용되지 않은 비트가 없습니다. 당신이 보았던 것처럼 비트를 주문하는 문제가 있지만, 최근에는 모두가 같은 주문에 정착했습니다. 지금까지 내가 아는 한, 현재의 컴파일러는 당신이 얻는 IO 데이터와 호환되지 않는 것을 생성하지 않을 것이다.