문제

가 아두이노 응용 프로그램(만 실제로는 도서관)를 수의 상태 플래그에서-그것은 원래 나는 단순히 선언대로 그들을 수(잘 uint8_t 그래서 8 비트 부호 없는 문자에,이 경우).그러나 나는 수가 있으로 그들을 모두 결합 하나의 정수와 사용되는 비트 마스크 작업을 설정하고 테스트하는 상태입니다.

전자의 예:

if (_shift == HIGH)
{
    _shift = LOW;
}
else
{
    _shift = HIGH;
}

후자의 예

#define SHIFT_BIT 0

if (bitRead(_flags, SHIFT_BIT) == HIGH)
{
   bitWrite(_flags, SHIFT_BIT, LOW);
}
else
{
   bitWrite(_flags, SHIFT_BIT, HIGH);
}

전 읽기 좋지만,후자의 더 효율적으(공간과 시간).야 하는 시간과 공간에 효율성을 항상이 상황에서는 이런 종류의 최적화만 일어날 때 필요?

(추가)

완전성을 위해 여기에 배선을 정의의 사람들 bitWrite etc.매크로:

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
도움이 되었습니까?

해결책

체크 아웃 Raymond Chen의 훌륭한 테이크 이 문제에 대한. 요약하면, 후자의 경우가 실제로 더 효율적인지 여부를 알아 내기 위해 자세한 계산을 수행해야합니다.

가독적 인 한, 회원 변수 로이 작업을 수행하는 것처럼 보이므로 아마도 좋은 기능으로 캡슐화했을 것입니다. 이 경우, 적어도 수업을 사용하는 사람들을위한 코드가 멋지게 보이기 때문에 가독성에 관심이 없습니다. 그러나 우려가있는 경우 항상 개인 기능으로 캡슐화 할 수 있습니다.

다른 팁

내가 확실하지 않은 AVR-GCC 컴파일러의 준수에 따라, 당신은 이런 일을하고 일을 멋지고 깨끗하게 유지할 수 있습니다.

struct flags {
    unsigned int flag1 : 1;  //1 sets the length of the field in bits
    unsigned int flag2 : 4;
}; 

flags data;

data.flag1 = 0;
data.flag2 = 12;

if (data.flag1 == 1)
{
    data.flag1 = 0;
}
else
{
    data.flag1 = 1;
}

한 번에 전체 플래그 int에 액세스하려면 :

union 
{
    struct {
        unsigned int flag1 : 1;  //1 sets the length of the field in bits
        unsigned int flag2 : 4;
    } bits;
    unsigned int val;
} flags;

그런 다음 2 레벨의 간접적으로 비트에 액세스 할 수 있습니다. variable.bits.flag1<-단일 비트 플래그를 반환하거나 단일 레벨을 반환하여 전체 int 가치의 플래그를 얻습니다. variable.val <-int를 반환합니다

상수를 사용할 필요가 없으면 더 명확 할 수 있습니다. HIGH 그리고 LOW, 두 가지 방법으로 분할하여. 그냥 만들어 bitSet 그리고 bitClear 행동 양식. bitSet 비트를 설정합니다 HIGH, 그리고 bitClear 비트를 설정합니다 LOW. 그런 다음 :

#define SHIFT_BIT 0

if (bitRead(_flags, SHIFT_BIT) == HIGH)
{
    bitClear(_flags, SHIFT_BIT);
}
else
{
    bitSet(_flags, SHIFT_BIT);
}

그리고 물론, 당신이 방금 가지고 있다면 HIGH == 1 그리고 LOW == 0, 당신은 == 점검이 필요하지 않습니다.

내 눈에는 후자의 코드조차도 여전히 읽을 수 있습니다. 각 깃발에 이름을 제시함으로써 코드를 많은 노력없이 읽을 수 있습니다.

불쌍한 방법은 "마법"숫자를 사용하는 것입니다.

if( _flags | 0x20 ) {  // What does this number mean?
   do_something();
}

최적화 할 필요가 없다면 가장 간단한 솔루션을 사용하지 마십시오.

최적화가 필요한 경우 다음 사항을 알아야합니다.

  • 첫 번째 버전은 비트를 토글하는 대신 비트를 설정하거나 지우는 경우 최소한 더 빠릅니다. 메모리를 읽을 필요가 없기 때문입니다.

  • 첫 번째 버전은 더 나은 WRT 동시성입니다. 두 번째에는 읽기 모듈식이 낭비가 있으므로 메모리 바이트에 동시에 액세스되지 않도록해야합니다. 일반적으로 인터럽트를 비활성화하여 인터럽트 대기 시간이 다소 증가합니다. 또한 인터럽트를 비활성화하는 것을 잊어 버린 것은 매우 불쾌하고 버그를 찾기가 어려울 수 있습니다 (지금까지 내가 겪은 가장 나쁘게 버그는 정확히 이런 종류였습니다).

  • 첫 번째 버전은 각 액세스가 단일로드 또는 저장 작업이기 때문에 최소한의 WRT 코드 크기 (플래시 사용량)입니다. 두 번째 접근 방식은 추가 비트 작업이 필요합니다.

  • 두 번째 버전은 특히 이러한 비트가 많은 경우 RAM을 적게 사용하는 것입니다.

  • 한 번에 여러 비트를 테스트하려면 두 번째 버전도 더 빠릅니다 (예 : 비트 세트 중 하나).

가독성, 비트 세트 및 C ++를 말하고 있다면 아무것도 찾지 못합니까? std::bitset 거기에? 나는 임베디드 프로그래머 경주가 비트 마스크에 대해 매우 편안하고, 깎아 지른 못생긴 (마스크가 아니라 마스크)에 대한 실명을 발전 시켰지만, 마스크와 비트 필드와는 별도로 표준 라이브러리는 매우 우아한 솔루션을 가지고 있습니다.

An example:

#include <bitset>

enum tFlags { c_firstflag, c_secondflag, c_NumberOfFlags };

...

std::bitset<c_NumberOfFlags> bits;

bits.set( c_firstflag );
if( bits.test( c_secondflag ) ) {
  bits.clear();
}

// even has a pretty print function!
std::cout << bits << std::endl;// does a "100101" representation.

비트 필드의 경우 논리적 작업을 사용하는 것이 좋습니다.

if (flags & FLAG_SHIFT) {
   flags &= ~FLAG_SHIFT;
} else {
   flags |= FLAG_SHIFT;
}

이것은 이제 후자의 효율성으로 전자의 모습을 가지고 있습니다. 이제 기능보다는 매크로를 가질 수 있습니다.

#define bitIsSet(flags,bit) flags | bit
#define bitSet(flags,bit) flags |= bit
#define bitClear(flags,bit) flags &= ~bit

호출 함수의 오버 헤드가 없으며 코드를 다시 읽을 수 있습니다.

나는 Arduino와 함께 연주하지 않았지만 이미 이런 종류의 매크로가있을 수 있습니다.

내가 말할 것이 먼저 나와 함께 걱정입니다:"#define SHIFT0" 왜 활용하지 않는 일정한 보다는 오히려 매크로?으로 훨씬 효율성이 얻는 일정한 허용하는 유형을 결정하는,따라서 확인하지 변환이 필요한 것입니다.

으로 효율성에 대한 당신의 기술:-먼저 제거하는 다른 절(는 조금 높은 경우 그 값은 이미 높은?) -두 번째,아보세요 뭔가를 읽을 수 있는 첫째,인라인 세터/getters 를 사용하여 비트를 내부적으로 마스킹을 할 것 작업을 효율적이고 읽을 수 있습니다.

으로 저장,C++내가 사용하는 경향이 있 bitset(와 결합 enum).

말하기에는 너무 간단합니까?

flags ^= bit;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top