비트 연산을 좀 간략하게 하려고 하는데
글쓴이: kkb / 작성시간: 금, 2011/04/22 - 1:38오후
비트 연산을 좀 간략하게 하려고 합니다.
unsinged long flags = 0;
위와 같이 플래그 변수가 있고요
#define BFLAG 0x01
#define LFLAG 0x02
비트가 정의되어 있습니다 2진수로는 각각 01 과 10 이겠죠?
flags 변수에 어떤 비트가 활성화되어 있는지 확인하려고 하는데
BFLAG와 LFLAG 둘 중에 하나는 무조건 활성화되어 있어야 하지만
둘다 활성화되어 있으면 에러입니다.
즉, flag == 01 or 10 은 OK이고
flag == 00 or 11은 에러입니다.
if ((flags & (BFLAG | LFLAG)) == 0) { printf("ERROR!\n"); return 1; } if ((flags & BFLAG) && (flags & LFLAG)) { printf("ERROR!\n"); return 1; }
위와 같이 하면 되기는 되는데
왠지 비트연산인 만큼 훨씬 간단하게 (또한 빈틈없이) 에러체크 될 거 같기도 해서요
어떤 방법이 있을까요?
실제로는 체크할 비트가 훨씬 많지만 일단 간단하게 두 개로 작성했습니다
비트연산이 좀 재밌는 거 같네요
Forums:
XOR 연산을 쓰면 어떨까요? ((flags &
XOR 연산을 쓰면 어떨까요?
((flags & BFLAG) ^ (flags & LFLAG))
답변 감사합니다
XOR 연산을 생각하기는 했는데
잘 안되네요
위와 같이 하면
00일때 에러
01일때 OK
10일때 OK
11일때 OK
입니다
11일때의 결과가 다르네요
(flags & BFLAG) ^ ((flags &
(flags & BFLAG) ^ ((flags & LFLAG) >> 1)
이렇게 한번 해보심이...
flags & BFLAG는 (값이 있다면) 0x1이고
flags & LFLAG는 0x2입니다.
그러니 둘을 XOR하면 둘다 1일경우 0이 되는게 아니라 3이 되겠죠.
답변 감사합니다
딱 봐도 결과는 잘 될 거 같네요
근데 (>> 1) 이 연산은 약간 끼워맞춘 느낌인데
비트 위치가 달라지면 또 그에 따라 조정을 해야 하고 비트위치도 알아야 하고
좋은 연산은 아니라는 생각이 듭니다
다른 좋은 방법은 없을까요?
밑이 2인 로그를 취하면 됩니다.대충 그런 함수가
밑이 2인 로그를 취하면 됩니다.
대충 그런 함수가 있다고 치고
LOG2(BFLAG) = 0
LOG2(LFLAG) = 1
만약 10000000b(128)인 XFLAG가 있다고 하면 (실수로 0x10000000이라고 썼네요. 급수정)
LOG2(XFLAG) = 7 이므로
1이 하나뿐이라는 플래그 규칙(?)만 만족한다면 문제 없을 것으로 보입니다.
이렇게 해봤습니다
이렇게 하니까 잘 되네요
왠지 더 복잡하게 만든 느낌도 들고;;
저라면
#define BFLAG (0x01 << 0)
#define LFLAG (0x01 << 1)
#define BIT_MASK (BFLAG | LFLAG)
if(!(flag & BIT_MASK) || (flag & BIT_MASK) == BIT_MASK)
// error!
더 복잡해지는거 같지만 if ( !!(flags &
더 복잡해지는거 같지만
if ( !!(flags & BFLAGS) == !!(flags & LFLAGS) )
이런 방법은 어떨까요?newflag =
이런 방법은 어떨까요?
newflag = flag+1
newflag == 10 or 11 은 OK
newflag == 01 or 100은 OK
newflag의 왼쪽에서 두번째 자리가 1인지 0인지만 판정하면 됩니다.
피할 수 있을때 즐겨라! http://melotopia.net/b
실제로 검사해야할 bit가 더 많다고 하셨으니까
실제로 검사해야할 bit가 더 많다고 하셨으니까 일반화하면
1. 0 일때 error
2. 하나 이상의 bit이 set되어 있으면 에러
이렇게 하면 bit수의 상관없이 원하는 값을 얻을수 있을것 같네요.
한표던집니다
한표던집니다
제가 보기엔 원 질문자의 코드가 더 이해하기
제가 보기엔 원 질문자의 코드가 더 이해하기 쉬워보이네요. :)
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://cinsk.github.io/cfaqs/
추천++
동감++
내 블로그: http://unipro.tistory.com
근데 확인해야할 플래그가 3개 이상이라면 좀 괴롭지
근데 확인해야할 플래그가 3개 이상이라면 좀 괴롭지 않을까요?
아마 비트 연산을 실제로 많이 안쓰시는분들은 거기까지
아마 비트 연산을 실제로 많이 안쓰시는분들은 거기까지 생각하진 못하셨을거예요.
답변 감사합니다
제가 질문글에서 올린 코드를 말씀하시는 건가요?
그러면 그냥 보기 쉽고 작성하기 쉽게 하나하나 풀어서 작성하는 것이 낫겠군요...;
네. 일단 저라면 질문 글에서 올린 코드를 쓸
네.
일단 저라면 질문 글에서 올린 코드를 쓸 겁니다. 다량의 데이터에 저런 비트 체크가 필요하다면 모를까, 한두번 검사할 내용이라면, 알아보기 쉬운 코드가 최고라는 생각이 드는군요.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://cinsk.github.io/cfaqs/
1. 좀 있어보이는 코드를 원하시는 건지, 2.
1. 좀 있어보이는 코드를 원하시는 건지,
2. 가독성이 좋은 코드를 원하시는 건지,
모르겠지만,
1의 측면에서. 라스코니님과 MasterQ님의 답변을 조합해서.
{{{
mask = (BFLAG | LFLAG | ...);
new_flag = flags & mask;
if ( new_flag == 0 ) // 모두 0인 경우
else if ( (new_flag-1) & new_flag ) // 1개 이상이 0인 경우
}}}
로 하시면 되겠네요..
http://realtimecollisiondetection.net/blog/?p=78
답변 감사합니다
좀 있어보이는 코드를 원하는 것도 아니고
가독성이 있는 코드를 원하는 것도 아닙니다
보여주기 위해 코딩을 할 만한 여유는 없습니다^^;
그냥 비트연산이기 때문에 왠지 간단한 코드로 구현 가능하지 않을까하고 생각했습니다
가끔 커널 소스 등을 보면 깜짝 놀랄 만큼 간단한 비트 연산으로 복잡한 비교를 한번에 구현한 코드들을 봅니다
그런 비트 연산을 직접 생각해서 만들어내는 것은 어려운데
한번 보면 쉽게 배워서 써먹을 수 있기 때문에
다른 분들에게 방법을 배워보려고 했습니다
비트 연산이라는 것이 보고 배우면 좀 재미있어서요
각각의 플래그 중...
하나만 활성화 되어있음을 보장하고 싶으신거라먄, 작성하신 첫번째 if 조건대로 하시고
popcount가 1인 조건 체크 혹은 MasterQ님의 것이 가장 좋아보입니다.
gcc를 사용하신다면 __builtin_popcount
댓글 달기