language/C language

C language :: 2

inz0i 2024. 11. 10. 13:24

C언어를 공부하며 진짜 시작이구나를 생각했던 구간

 

비트 단위 연산자가 필요한이유

비트는 0과 1을 저장할수 있는 공간이다 자료를 저장할수 있는 프로그램을 만들 때 비트 단위로 연산한다면 메모리를 많이 절약 할수 있다는 장점을 가지고 있다.

 

data = 0110 1010 //2진수

data = 0x5A 16진수 로 표현이 가능하다.

 

0 X 0 1 1 0 1 0
7번 비트 6번 비트  5번 비트  4번비트 3번 비트  2번 비트 1번 비트  0번 비트 

오른쪽에서 윈쪽으로 갈수록 비트 번호가 커진다

 

시프트 연산자

시프트 연산자 <<, >> 는 변수의 값을 지정한 비트 수만큼 왼쪽 또는 오른쪽으로 비트를 이동시키는 기능을함 

 

//오른쪽에서 왼쪽으로 이동

// 변수 << 이동할 비트 수
unsigned char data = 0x1A;
//이동전 : 0001 1010
data = data <<2;
//이동후 0110 1000
//왼쪽에서 오른쪽으로 이동

//변수 >> 이동할 비트 수

unsigned char data = 0x1A;
//이동전 0001 1010
data = data >> 2;
//이동후 0000 0110

 

이동한 비트들이 메모리 공간의 크기를 벗어나면 해당비트들은 사라지고 비트가 이동한 빈자리에는 0이 채워집니다.

비트가 왼쪽으로 이동해서 사라지는것을 오버플로우(Overflow)라고 부르고

오른쪽에서 이동해서 사라지는것을 언더플로우(Underflow)라고 부릅니다.

 

 

<< *2       /2>>

10진수 16 8 4 2 1
2진수  0001 0000 0000 1000 0000 0100 0000 0010 0000 0001

<<연산을 사용하여 n개의 비트를 오른쪽에서 왼쪽으로 이동하면 2n을 곱한 것과 같고 

>>연산을 사용하여 n개의 비트를 왼쪽에서 오른쪽으로 이동하면 2n을 나눈것과 동일하다 .

즉 data = data <<3은 data = data*2의3승 과 같다는 뜻이고 data = data >>2 는 data = data/2의2승과 같다 

 

시프트 연산자 사용시 주의할점 

시프트 연산자의 우선순위가 + 덧셈 연산자보다 낮다 그래서 곱셈 나눗셈 로 이루어진 수식을 그대로 사용할 경우 잘못된 결과가 나올수 있다. 이문제를 해결할려면 괗로를 이용하여 결과값을 도출하면 된다.

비트 연산자

 비트 연산자는 비트 단위로 AND(&), OR(|), XOR(^), NOT(~) 연산을 수행합니다. 

 C language :: 1 장 참조

 

AND(&)연산

두 값을 비트 단위로 AND 연산을 수행 

 0000 1111(0x0F)
&0011 1100(0x3C)
---------------
 0000 1100(0x0C)

 

OR(|)연산

두 값을 비트 단위로 OR연산을 수행

 0000 1111(0x0F)
|0011 1100(0x3C)
----------------
 0011 1111(0x3F)
 

 

XOR(^) 연산

두 값을 비트 단위로 XOR연산을 수행

 0000 1111(0x0F)
^0011 1100(0x3C)
----------------
 0011 0011(0x33)

 

 

NOT(~) 연산

각 비트의 값을 반전 시키는 작업을 수행

~0000 1111(0x0F)
----------------
 1111 0000(0xF0)

 

 

지정한 비트를 0으로 설정하기

AND 연산자 &을 사용하면 된다.

 ???? ???? //?는 0,1인지 알수없음
&1111 1011 // 2번 비트만 0으로 설정함
--------- 
 ???? ?0?? //2번 비트만 0으로 바뀜

임의의 비트를 1로 설정할수있습니다. 

0x04를 직접 명시하지 않고 2번비트라는 정보만 가지고 만들어보면 ... 

unsigned char lpam_state; //lamp_state 에 어떤값이 있는지 알 수 없음
unsigned char bit_num = 2; // 1로 만들 비트 번호
unsigned char mask = 0x01 << bit_num; //0x04
lamp_state = lamp_state | mask // lamp_state의 2번 비트만 1로 변경

 

이를 함수로 만들어보면 

#include <stdio.h>

unsigned char SetBit(unsigned char dest_data, unsigned char bit_num)
{
    if (bit_num < 8) dest_data = dest_data | (0x01 << bit_num);
    return dest_data;
}

void main()
{
    unsigned char lamp_state = 0x77;   /* 0x77 → 0111 0111 */
    printf("%X->", lamp_state);        /* 변경 전 값 출력 */
                                       /* lamp_state 변수의 3번째 비트를 1로 설정 */
    lamp_state = SetBit(lamp_state, 3);  /* 0x7F → 0111 1111 */
    printf("%X\n", lamp_state);   /* 변경 후 값 출력 */
}

결과값

이러한 방법을 통해 원하는 비트의값 , 보수이용, 데이터 암호화 등등 가능하다

더보기

1장보단 어렵지만 아직할만하다