비트 연산을 좀 간략하게 하려고 하는데

kkb의 이미지

비트 연산을 좀 간략하게 하려고 합니다.

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;
	}

위와 같이 하면 되기는 되는데
왠지 비트연산인 만큼 훨씬 간단하게 (또한 빈틈없이) 에러체크 될 거 같기도 해서요

어떤 방법이 있을까요?
실제로는 체크할 비트가 훨씬 많지만 일단 간단하게 두 개로 작성했습니다
비트연산이 좀 재밌는 거 같네요

planetarium의 이미지

XOR 연산을 쓰면 어떨까요?
((flags & BFLAG) ^ (flags & LFLAG))

kkb의 이미지

XOR 연산을 생각하기는 했는데
잘 안되네요

	if (!((flags & BFLAG) ^ (flags & LFLAG)))
	{
		printf("ERROR!\n");
		return 1;
	}

위와 같이 하면
00일때 에러
01일때 OK
10일때 OK
11일때 OK
입니다

11일때의 결과가 다르네요

hoppang의 이미지

(flags & BFLAG) ^ ((flags & LFLAG) >> 1)

이렇게 한번 해보심이...

flags & BFLAG는 (값이 있다면) 0x1이고
flags & LFLAG는 0x2입니다.
그러니 둘을 XOR하면 둘다 1일경우 0이 되는게 아니라 3이 되겠죠.

kkb의 이미지

딱 봐도 결과는 잘 될 거 같네요

근데 (>> 1) 이 연산은 약간 끼워맞춘 느낌인데
비트 위치가 달라지면 또 그에 따라 조정을 해야 하고 비트위치도 알아야 하고
좋은 연산은 아니라는 생각이 듭니다
다른 좋은 방법은 없을까요?

hoppang의 이미지

밑이 2인 로그를 취하면 됩니다.

대충 그런 함수가 있다고 치고

LOG2(BFLAG) = 0
LOG2(LFLAG) = 1

만약 10000000b(128)인 XFLAG가 있다고 하면 (실수로 0x10000000이라고 썼네요. 급수정)

LOG2(XFLAG) = 7 이므로
1이 하나뿐이라는 플래그 규칙(?)만 만족한다면 문제 없을 것으로 보입니다.

kkb의 이미지

	if (!(!(flags & BFLAG) ^ !(flags & LFLAG)))
	{
		printf("ERROR!\n");
		return 1;
	}

이렇게 하니까 잘 되네요
왠지 더 복잡하게 만든 느낌도 들고;;
라스코니의 이미지

#define BFLAG (0x01 << 0)
#define LFLAG (0x01 << 1)

#define BIT_MASK (BFLAG | LFLAG)

if(!(flag & BIT_MASK) || (flag & BIT_MASK) == BIT_MASK)
// error!

planetarium의 이미지

더 복잡해지는거 같지만
if ( !!(flags & BFLAGS) == !!(flags & LFLAGS) )

snowall의 이미지

이런 방법은 어떨까요?

newflag = flag+1

newflag == 10 or 11 은 OK
newflag == 01 or 100은 OK

newflag의 왼쪽에서 두번째 자리가 1인지 0인지만 판정하면 됩니다.

피할 수 있을때 즐겨라! http://melotopia.net/b

MasterQ의 이미지

실제로 검사해야할 bit가 더 많다고 하셨으니까 일반화하면
1. 0 일때 error
2. 하나 이상의 bit이 set되어 있으면 에러

if (!flag ||((flag - 1) & flag))
   return ERROR;
return OK;

이렇게 하면 bit수의 상관없이 원하는 값을 얻을수 있을것 같네요.

익명 사용자의 이미지

한표던집니다

cinsk의 이미지

제가 보기엔 원 질문자의 코드가 더 이해하기 쉬워보이네요. :)

unipro의 이미지

동감++

내 블로그: http://unipro.tistory.com

익명 사용자의 이미지


근데 확인해야할 플래그가 3개 이상이라면 좀 괴롭지 않을까요?

익명 사용자의 이미지

아마 비트 연산을 실제로 많이 안쓰시는분들은 거기까지 생각하진 못하셨을거예요.

kkb의 이미지

제가 질문글에서 올린 코드를 말씀하시는 건가요?
그러면 그냥 보기 쉽고 작성하기 쉽게 하나하나 풀어서 작성하는 것이 낫겠군요...;

cinsk의 이미지

네.

일단 저라면 질문 글에서 올린 코드를 쓸 겁니다. 다량의 데이터에 저런 비트 체크가 필요하다면 모를까, 한두번 검사할 내용이라면, 알아보기 쉬운 코드가 최고라는 생각이 드는군요.

익명 사용자의 이미지

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

kkb의 이미지

좀 있어보이는 코드를 원하는 것도 아니고
가독성이 있는 코드를 원하는 것도 아닙니다

보여주기 위해 코딩을 할 만한 여유는 없습니다^^;

그냥 비트연산이기 때문에 왠지 간단한 코드로 구현 가능하지 않을까하고 생각했습니다
가끔 커널 소스 등을 보면 깜짝 놀랄 만큼 간단한 비트 연산으로 복잡한 비교를 한번에 구현한 코드들을 봅니다

그런 비트 연산을 직접 생각해서 만들어내는 것은 어려운데
한번 보면 쉽게 배워서 써먹을 수 있기 때문에
다른 분들에게 방법을 배워보려고 했습니다

비트 연산이라는 것이 보고 배우면 좀 재미있어서요

kalevala의 이미지

하나만 활성화 되어있음을 보장하고 싶으신거라먄, 작성하신 첫번째 if 조건대로 하시고

popcount가 1인 조건 체크 혹은 MasterQ님의 것이 가장 좋아보입니다.

gcc를 사용하신다면 __builtin_popcount

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.