Developer

12.(C언어) 논리 연산자,비트 연산자 본문

Programming Language/C

12.(C언어) 논리 연산자,비트 연산자

DPhater 2020. 8. 1. 21:07

C언어에는 값을 논리적으로 판단하는 논리 연산자와, 비트 단위로 연산을 수행하는 비트 연산자가 존재한다.

논리 연산자

논리 연산자는 True(참), false(거짓)으로 연산을 수행하는 것이다. C에서는 0은 거짓 이고, 0이외의 모든 값은 참으로 인식한다. 논리 연산에는 AND(논리곱),OR(논리합),NOT(논리 부정) 가 있다.

AND는 양쪽 모두 참일때 참, OR는 양쪽 중 하나만 참이면 참, NOT은 참이라면 거짓으로, 거짓이라면 참으로 변화

이제 직접 C에 있는 논리 연산자를 살펴보자

C에서 AND는 &&

OR는 ||

NOT은 ! 연산자를 사용한다.

#include<stdio.h>
int main(){
	printf("논리곱\n");
    printf("%d\n",0&&0);
    printf("%d\n",0&&1);
    printf("%d\n",1&&0);
    printf("%d\n",1&&1);
    
    printf("논리합\n");
    printf("%d\n",0||0);
    printf("%d\n",0||1);
    printf("%d\n",1||0);
    printf("%d\n",1||1);
    
    printf("논리 부정\n");
    printf("%d\n",!0);
    printf("%d\n",!1);
    printf("%d\n",!2);
    return 0;
}

코드1 실행 결과

위의 설명처럼 논리곱(&&)은 둘다 1일때 참을 반환하고, 논리합(||)은 하나라도 1이면 참을 반환하며, 논리 부정(!)은 참 거짓을 반대로 뒤집는다. 여기에서 1이아니라 0이 아닌 어떤 수를 써도 결과는 똑같이 나온다. 0을 제외한 모든 수가 참이기 때문이다.

 그리고 또 한가지 중요한점은 컴퓨터는 빠른 논리연산을 수행한다는 점이다. 빠른 논리연산이란 확인 하지 않아도 되는값은 확인하지 않고 바로 결과를 반환하는것이다. 논리곱(&&)의 경우 둘다 1일 경우에만 참 이므로 처음 항목이 거짓이라면 뒤의 항목은 확인하지 않고 거짓을 반환한다. 논리합(||)의 경우 둘중 하나만 1이면 참 이므로 처음 항목이 참이라면 뒤의 항목은 확인하지 않고 참을 반환한다. 또한 a>b와 같은 비교 연산자도 결과가 참 거짓으로 나오므로 논리 연산을 수행할 수 있다.

#include<stdio.h>
int main(){
	int a=30;
	int b=11;
	int c=18;
	int d=19;
	printf("%d",a>b&&c<d);
	return 0;
}

코드2 실행 결과

코드2에서는 a>b && c<d 를 출력하고 있다. a>b 부터 생각해보자

30이 11보다 큰게 맞기때문에 참이다. 그리고 c가 d보다 작기 때문에 c<d도 참이다. 따라서 참 && 참 이므로 참 값인 1이 출력 되는것을 알 수 있다.

비트 연산자

비트 연산자는 연산이 비트 단위로 수행이된다. bit는 진법에서 말했듯이 0과1이 들어갈 수 있는 하나의 장소이다. 비트 연산자의 종류는 아래 표와 같다.

연산자

설명

&

비트단위 AND

|

비트단위 OR

^

비트단위 XOR

~

비트단위 NOT

<<

비트를 왼쪽으로 Shift

>>

비트를 오른쪽으로 Shift

위의 연사자를 이용해 &= , |= 등 +=과 같은 연산자도 있다.

#include<stdio.h>
int main(){
	unsigned char ch1=12,ch2=4;
	
	printf("%u\n",ch1&ch2);
	printf("%u\n",ch1|ch2);
	printf("%u\n",ch1^ch2);
	return 0;
}

코드3 실행 결과

unsigned char은 1byte 즉 8bit이다.(부호비트가 영향을 받지않도록 unsigned)

따라서 ch1에는 0000 1100 이 들어있고,

ch2에는 0000 0100이 들어있다.

&연산부터 차례대로 해보자

0000 1100

&0000 0100

--------------

0000 0100 이 나오고 10진수로 4인것을 확인 할 수 있다.

&연산의 경우 둘다 1일때만 1이된다.

0000 1100

| 0000 0100

-----------------

0000 1100 이 나오고 10진수로 12인것을 확인 할 수 있다.

|연산의 경우 둘중 하나만 1이면 1이 된다.

&와 |은 논리 연산에서 배웠으니 이해가 될것이다.

이번엔 XOR을 해보자

0000 1100

^0000 0100

----------------

0000 1000

XOR은 두 비트가 같을 경우 0 다르면 1이 나오는 연산이다.

이제 시프트 연산자를 알아보자

시프트 연산자는 a<<b 혹은 a>>b와 같이 사용한다.

a<<b는 a의 비트를 왼쪽으로 b번 이동하라는 뜻이고

a>>b는 a의 비트를 오른쪽으로 b번 이동시키라는 뜻이다.

#include<stdio.h>
int main(){
	unsigned char ch1=1;
	printf("%d\n",ch1<<3);
	printf("%d\n",ch1>>3);
	return 0;
}

코드4 실행 결과

최초의 ch1의 비트 상태를 보자

0

0

0

0

0

0

0

1

이 상태에서 ch1<<3을 수행하였다. ch1의 비트를 왼쪽으로 3번 이동시키는 것이므로

0

0

0

0

1

0

0

0

빈 공간은 0으로 채워지며 이렇게 8이 된다.

이번에는 ch1>>3을 수행하면 오른쪽으로 3번 이동시키는 것이므로

0

0

0

0

0

0

0

0

비는 공간은 0으로 채워지며 시프트 연산에서 첫째 자리나 마지막 자리를 넘어서는 비트는 그대로 사라지게된다.따라서 ch1>>3은 0이 되는 것이다.

시프트 연산에서는 주의할 점이 있다. 만약 부호가 있는 자료형에 시프트 연산을 사용하게된다면 부호 비트를 생각해야 하기 때문이다.

<<연산의 경우 부호가 없는 연산과 같이 비어진 곳을 0으로 채우며 왼쪽으로 이동시킨다.

>>연산의 경우 달라지는데 부호가 없는 연산에서는 빈공간을 무조건 0으로 채우며 이동 했지만 부호가 있는 >>연산에서는 부호비트로 빈 공간을 채우며 이동한다.

비트 연산은 플래그 처리를 할때 아주 유용하다.

1바이트로 8가지 상태를 저장할 수 있어 저장공간을 효율적으로 사용할 수 있다.

연산자 우선순위

우선순위

연산자 유형

연산자

결합방향

높다

낮다

괄호,배열,구조체

() [] -> .

->

단항 연산

- ~ ++ -- & *

<-

산술

연산

* / %

->

+ -

시프트 연산

>> <<

관계

연산

비교

< <= > >=

등가

== !=

비트 논리 연산

& | ^

논리 연산

&& “”

조건 연산

?:

<-

대입

연산

대입

=

<-

축약형 대입

+= -=

축약형비트대입

>>= <<=

나열 연산

,

->

단항 연산의 *은 이후에 나오는 포인터 역참조 연산자 이고 산술연산의 *은 곱하기 연산자 이다.

'Programming Language > C' 카테고리의 다른 글

14.(C언어) 반복문_for,while  (0) 2020.08.01
13.(C언어) 조건문_if,switch  (0) 2020.08.01
11.(C언어) 형 변환  (0) 2020.08.01
10.(C언어) 연산, 연산자  (0) 2020.08.01
9.(C언어) scanf, 입력받기  (0) 2020.08.01
Comments