공부했던 자료 정리하는 용도입니다.

재배포, 수정하지 마세요.

 

 


 비트 연산자 

  • 비트 연산자의 종류
  • 시프트 연산
  • 플래그(flag)와 마스크
  • XOR 연산의 특성

 


 

비트연산자

  비트 연산자는 비트로 옵션을 설정할 때 주로 사용하며 저장 공간을 아낄 수 있는 장점이 있다. 이와 같은 방식을 플래그(flag)라고 하며, 연산과 할당이 한꺼번에 이루어지는 연산자는 플래그를 켜거나 끌 때 유용하게 활용된다.

 

  • bit : 2진수를 저장하는 단위. 컴퓨터에서 사용하는 최소 단위이며 0과 1을 나타낸다.
    최상위 비트(Most Significant Bit, MSB) : 첫 번째 비트 
    최하위 비트(Least Significant Bit, LSB) : 마지막 비트
  • byte : 8 bit 크기의 단위

 

  ■ 비트 연산자의 종류

연산자 설  명
& 비트 AND
| 비트 OR
^ 비트 XOR(배타적 OR, Exclusive OR)
~ 비트 NOT
<< 비트를 왼쪽으로 시프트
>> 비트를 오른쪽으로 시프트
&= 비트 AND 연산 후 할당
|= 비트 OR 연산 후 할당
^= 비트 XOR 연산 후 할당
<<= 비트를 왼쪽으로 시프트한 후 할당
>>= 비트를 오른쪽으로 시프트한 후 할당

 

 

시프트 연산

[변수] << [이동할 비트 수];
[변수] >> [이동할 비트 수];

  지정한 횟수대로 비트를 이동시킨다. ``<<``은 2의 거듭제곱을 곱한 효과, ``>>``은 2의 거듭제곱을 나눈 결과와 같다. 시프트 연산은 자료형의 부호 여부에 따라 동작과정이 다르다. 부호있는 자료형에 시프트 연산을 하는 경우 의도치 않은 결과가 나올 수 있으므로 항상 부호 비트를 고려해서 연산해야 한다.

  • 부호 없는 자료형 : 첫째 자리나 마지막 자리를 넘어서는 비트는 사라지며, 모자라는 공간은 0으로 채운다.
  • 부호 있는 자료형 : 부호 있는 자료형과 방법은 같지만 ``>>``일 경우 부호비트로 채워지고, ``<<``일 경우 0으로 채워진다. 이 과정에서 부호 비트를 덮어씌우게 되면 부호가 바뀐다.

 

 

플래그(flag)와 마스크

  플래그는 적은 공간에 정보를 저장해야 하고, 빠른 속도가 필요할 때 사용한다.(ex CPU) 플래그와 마스크를 OR연산하면 플래그를 켤 수 있다(이미 켜진 경우에는 그대로 유지) 비트를 끌때는 NOT연산을 이용하고 특정 비트가 켜져 있는지 검사할 때는 &연산자를 사용한다.

 

  • 마스크(mask) : 플래그의 비트를 조작하거나 검사할 때 사용하는 숫자
  • 토글(toggle) : 두 가지 상태만을 가지고 있는 스위치이다. 누를 때마다 값이 전환된다.
#include <stdio.h>

int main(void)
{
	int i;
	int result;
	unsigned char flag = 0;
	printf("before : %u\n", flag);
	
	// 10진수 2진수로 변환해서 출력 
	result = flag;
	for(i = 128; i >= 1 ; i = i / 2)
	{
		printf("%d", result / i);
		if (i == 16)
			printf(" ");
		result %= i;		
	}
	
	flag |= 1;	// 마스크값 0000 0001과 OR연산해서 8번째 비트를 켠다.
	flag |= 2;	// 마스크값 0000 0010과 OR연산해서 7번째 비트를 켠다. 
	flag |= 4;	// 마스크값 0000 0100과 OR연산해서 6번째 비트를 켠다. 
	
	printf("\n------------------\n");
	printf("6 ~ 8번째 켠 후: %u\n", flag);	// 0000 0111이므로 7
	
	// 10진수 2진수로 변환해서 출력 
	result = flag;
	for(i = 128; i >= 1 ; i = i / 2)
	{
		printf("%d", result / i);
		if (i == 16)
			printf(" ");
		result %= i;		
	}
		
	flag &= ~2;	// 마스크값 2의 비트를 뒤집은뒤(1111 1101) AND연산해서 7번째 비트를 끈다. 	
	printf("\n------------------\n");
	printf("7번째 끈 후 : %u\n", flag);	// 0000 0101이므로 5
	
	// 10진수 2진수로 변환해서 출력 
	result = flag;
	for(i = 128; i >= 1 ; i = i / 2)
	{
		printf("%d", result / i);
		if (i == 16)
			printf(" ");
		result %= i;		
	}
	
	flag ^= 1;	// 마스크값 0000 0001과 XOR 연산해서 8번째 비트 토글 
	flag ^= 8;	// 마스크값 0000 1000과 XOR 연산해서 5번째 비트 토글 
	
	printf("\n------------------\n");
	printf("5, 8번째 토글 후 : %u\n", flag);	// 0000 1100이므로 12

	// 10진수 2진수로 변환해서 출력 
	result = flag;
	for(i = 128; i >= 1 ; i = i / 2)
	{
		printf("%d", result / i);
		if (i == 16)
			printf(" ");
		result %= i;		
	}
	return 0;
}

플래그를 사용하는 예시이다.

``플래그 |= 마스크`` 해서 플래그를 켜고, ``플래그 &= ~마스크``해서 플래그를 끈다. (토글은 ``플래그 ^= 마스크``)
``플래그 &= 마스크``해서 플래그가 켜져있는지 검사한다. 

 

 

XOR 연산의 특성과 사용예시

a ^ b = c
c ^ b = a
c ^ a = b

XOR은 위와 같은 특성을 가진다.

  • 간단한 암호화
    평문과 암호키를 비트 XOR연산하면 암호화된 값이 나온다. 암호화된 값과 암호키를 다시 XOR연산하면 값이 복호화되어 평문이된다.
  • 임시 변수 없이 두 변수의 값을 바꾸기
    임시 변수없이 XOR 연산자를 세 번 사용해서 두 변수의 값을 바꿀 수있다.
#include <stdio.h>

int main()
{
    int a = 10;
    int b = 20;
    
    printf("a : %d, b : %d\n", a, b);
    
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    
    printf("a : %d, b : %d\n", a, b);
    return 0;
}

XOR 연산자로 두 변수의 값을 바꾸는 예시이다.

 

 

 

'기타 > C' 카테고리의 다른 글

[C] 파일의 분할, 헤더파일  (0) 2020.06.17
[C] 매크로와 선행 처리기(Preprocessor)  (0) 2020.06.16
[C] 메모리 구조와 동적할당  (0) 2020.06.15
[C] 공용체(Union Type), 열거형(Enumerated Type)  (0) 2020.06.08
[C] 구조체  (0) 2020.06.01

+ Recent posts