본문 바로가기

c

비트 단위 연산

1. 비트 논리 연산자

2. 비트 이동 연산자


왼쪽 이동 연산자(<<)
오른쪽 피 연산자에 지정된 자릿수 만큼 왼쪽 피연산자의 비트들을 왼쪽으로 이동
비게 되는 비트들은 0이 채워 진다.

ex) 7 << 2 = 28 = 7*(2^2)

일반 적으로 공간이 충분할 때  M <<n = m*(2^n)

오른쪽 이동 시프트(>>)
오른쪽으로 이동 밀려난 비트들은 무시된다.
unsigned 형 일 경우 비게된 비트에 0이 채워짐
signed형 일 경우 시스템에 따라 다르다. 0이 채워지거나 가장 왼쪽비트가 복사

 ex) unsigned인 경우 7 >> 2 = 1 = 7 / (2^2)

 일반적으로 m이 음수가 아닐 경우  m>>n = m /(2^n)

 

주의할점

 쉬프트 연산의 피연산자는 주로 부호없는 정수형(unsigned)이며, 실수형은 당연히 안된다.

부호있는 정수형(signed)은 가능은 하지만 최상위 비트 때문에 시스템이나 컴파일러에 따라 동작이 조금 달라진다. 

부호있는 정수에 대한 쉬프트 연산은 권장되지 않으며 실제로 의미를 가지는 경우도 드물다. 

 

이용

위와 같이 쉬프트연산은 곱셈연산을 대체할 수 있는데

CPU입장에서 비트를 이동시키는 것(쉬프트연산)과 더하는 것을 반복하는 것(곱셈연산)은

완전히 다른 작업이므로 곱셈연산과 쉬프트 연산은 속도차가 무려 10배 정도 난다고 한다.

쉬프트 연산이 곱셈에 비해 불리한 점은 2의 거듭승에 대해서만 곱셈이 가능하다는 점이다.

 2배, 4배, 8배, 16배 등만 할 수 있으며 3배, 17배 이런 연산은 할 수 없다. 그러나 쉬프트 연산과 덧셈, 뺄셈을 잘 조합하면 이런 연산이 가능해지기도 한다. 

3배 : a << 1 + a;

9배 : a << 3 + a;

15배 : a << 4 - a;

60배 : a << 6 - a << 2; 

정밀하게 측정해 보면 이런 연산들이 곱셈보다 수배~수십배 더 빠르다.

보통의 경우라면 일반적인 곱셈을 하는 것이 소스를 유지하기에 편리하지만 속도가 지극히 중요하다면 곱셈보다는 가급적이면 쉬프트 연산을 사용하는 것이 좋다. 

 

3. 비트 마스크

변수나 수식에서 원하는 비트만을 선택하거나 변경하기 위한 상수나 변수를 비트 마스크(bit mask)라고 한다.

n이 비트자리수 일때, mask = 1 << (n-1)



ex) 10진수를 2진수(문자열)로 추출하는 함수

 
char* itobs(int n, char* ps){  
    int i;   
   static int size = 8*sizeof(int);
   for(i=size-1 ; i>=0 ; i--,n>>=1)
      ps[i]=(01&n)+'0';
      ps[size]=\0';
      return ps;
}



4. 비트 필드 조작

비트 필드 - 서로 이웃하는 비트의 맴버를 지닌 구조체


비트 필드의 선언

 struct{
    자료형 변수명 : 비트수; //비트필드  
  }structName;

기본적으로 자료형은 정수형만 가능하며(실수나 포인터형은 불가) 

C언어에서는 int와 unsigned int이 가능하지만 일반적으로 unsigned int를 사용한다.

한 개의 비트필드는 unsigned int형의 비트수 이상으로 비트수를 선언할 수 없다.



여러개의 비트필드가 존재할 때 한 필드는 두 int형 사이의 경계선에 걸쳐서 저장될 수 없다.

 컴파일러는 자동으로 필드를 이동시켜 int의 경계선에 정렬되도록한다. int형에 빈공간이 있게된다.

ex) 비트가 왼쪽에서 오른쪽으로 채워진다고 가정하면




변수명이 없는 비트 필드를 선언하여 선언한 비트수로 필드 구조를 채울수 있다.

변수명이 없는 비트 필드를 0으로 지정하면 경계선을 넘어 다음 int에 저장된다.

ex)

 struct{
   unsigned int year : 20;
   unsigned int : 0;
   unsigned int month : 4;
   unsigned int day : 5 ;
   unsigned int : 5;
   unsigned int hour : 5;
   unsigned int min : 6;

}time;

비트가 왼쪽에서 오른쪽으로 채워진다고 가정하면

'c' 카테고리의 다른 글

기본 논리  (0) 2012.11.20
출력형식(printf) 변환명세와 필드값 정렬  (0) 2012.11.20
함수와 2차원 배열로의 전달인수  (1) 2012.11.15
n비트에서 -a의 2의 보수 계산 방법  (0) 2012.11.15
다차원 배열과 포인터  (0) 2012.11.14