상상해보십시오! 일부 집 자동화를 처리하는 IO 인터페이스에서 uint8_t data[8]
으로 8 바이트를받습니다. 이 8 바이트는 휴한지로 해석해야합니다어떻게 매핑 된 메모리의 비트에 액세스합니까?
가 어떻게 올바른 비트 액세스합니까? 는 지금 생각에 대한 두 가지 솔루션 :
해결 방법 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을 사용할 수 있습니까?
내 질문은 : 올바른 비트를 어떻게 액세스해야합니까?
비트 필드는 휴대용이며 C 표준의 일부입니다. 그것은 코드 가독성과 습관의 문제입니다 : 제 경우에는 비트 마스크를 선호하지만 많은 사람들이 비트 파일을 선호합니다. – LPs
MISRA가 비트 필드의 사용을 금지하는 데 사용되었지만 여전히 사용되는지는 알 수 없습니다. – Toby
#define 매크로를 사용하여 솔루션 2를 훨씬 쉽게 읽을 수있게 만들 수 있습니다. 장래에 변경 작업을하는 데 필요한 작업량을 줄이는 이점이있는 단 한 곳에서만 읽을 수없는 추악한 것들을 완성하게 될 것입니다. –