Algorithm/C언어

[ 4. C언어의 기본 - 연산자 ]

대시 2021. 9. 30. 11:02

이번 포스팅은 연산자를 알아보도록 하겠습니다.

 

1) 연산자의 종류
분류 연산자
대입 연산자 =
산술 연산자 +, -, *, /, %
복합 대입 연산자 +=, -=, *=, /=, %=
증감 연산자 ++, --
관계 연산자 >, <, ==, !=, >=, <=
논리 연산자 &&, | |, ! 
조건 연산자 ?:
비트 논리 연산자 &, |, ^, ~ 
비트 이동 연산자 >>, <<

1) 대입 연산자

#include <stdio.h>
int main(){
 
  int A = 10, B = 20;
 
  A = B;
 
  printf("%d\n", A);
}
cs

A = B, B의 값을 A에 저장한다. 결괏값:20

1-1) 복합 대입 연산자 : 선 산술 후 대입 A += 5, A에 5를 먼저 더하고 후에 값을 다시 대입

#include <stdio.h>
int main(){
 
  int A = 13, B = 20, C = 30, D = 40, E = 9, F= 7;
 
  A += B;
  printf("A += B는 %d 이다.\n", A);
 
  A -= C;
  printf("A -= C는 %d 이다.\n", A);
 
  C *= D;
  printf("C *= D는 %d 이다.\n", C);
 
  C /= D;
  printf("D /= C는 %d 이다.\n", C);
 
  E %= F;
  printf("E %%= F는 %d 이다.\n", E);
}
cs

▶ A += B 

- A와 B를 더한 값을 A에 저장한다. 결괏값 = 33

▶ A -= C

- A와 C를 뺀 값을 A에 저장한다. 결괏값 = 3  ( 33 - 30 )

 

▶ C *= D

- C와 D를 곱한 값을 C에 저장한다. 결괏값 = 1200 ( 30 * 40 )

 

▶ C /= D

- C를 D로 나눈 값을 C에 저장한다. 결괏값 = 30 ( 1200 / 40 )

 

▶ E %= F

- E를 F로 나누고, 나머지 값을 E에 저장한다. 결괏값 = 2 ( 9 % 7 ) 

 

2) 증감 연산자 : 선 연산 후 증감, 선 증감 후 연산으로 나뉜다.

증감 연산자의 종류에는 증가 연산자(++)와 감소 연산자( -- )의 두 가지 형태가 있는데,

연산자가 변수의 앞에 있는가 뒤에 있는가에 따라 전위형(Prefix)과 후위형(Postfix)으로 나눠어진다.

 

전위형은 ++a, --a 의 형태이고, 후위형은 a++. a-- 의 형태인데, 이들의 연산 결과는 다르기 때문에

주의하여 사용하여야 한다.

 

먼저 코드를 살펴보자.

#include <stdio.h>
int main(){
 
  int a = 10,b = 10;
  
  b = ++a;
  printf(" a = %d, b = %d\n", a, b);
 
  b = --a;
  printf(" a = %d, b = %d\n", a, b);
 
  b = a++;
  printf(" a = %d, b = %d\n", a, b);
 
  b = a--
  printf(" a = %d, b = %d\n", a, b);
}
cs

 

연산식 실행 절차 실행 결과
 b = ++a 

b = --a

b = a++

b = a--
a에서 1을 더한 후 그 값을 b에 대입한다.

a에서 1을 뺀 후 그 값을 b에 대입한다.

a를 b에 대입한 후 a에 1을 더한다.

a를 b에 대입한 후 a에 1을 뺀다.
a = 11, b = 11

a = 9, b = 9

a = 11, b = 10

a = 9, b = 10

※ 위 코드로 실행하면 위의 표와 결괏값이 다를 수 있습니다.

- 위에서 대입한 값들을 호출하므로 값이 다를 수 있습니다. (표는 한줄씩 실행한 결과라고 생각하면 됨)

 

3) 관계 연산자 : 두 수의 관계를 비교하여 참(True) 또는 거짓(False)의 결과를 얻는다.

                 거짓은 0, 참은 1로 사용되지만 0외의 모든 숫자도 참으로 간주한다.

연산자 형식 의미
< 식1 < 식2 식1 이 식2보다 작다.
<= 식1 <= 식2 식1 이 식2보다 작거나 같다.
> 식1 > 식2 식1 이 식2보다 크다.
>= 식1 >= 식2 식1 이 식2보다 크거나 같다.
== 식1 == 식2 식1 이 식2와 같다
!= 식1 != 식2 식1 이 식2와 같지 않다.

모든 관계 연산자는 같은 우선 순위를 가지며, 왼쪽에서 오른쪽으로 연산이 이루어진다.

따라서 관계 연산자는 프로그램이 수행되는 도중에 데이터나 계산 결과 등이 어떤 조건에 맞는지

판단하여 그 결과에 따라 실행할 명령문을 선택하는 데 이용된다.

 

#include <stdio.h>
int main(){
 
  int a = 10, b = 20, c = 30, result;
  
  result = a > b;   // 0
  printf(" 결괏값은 %d 이다.\n", result);
 
  result = 19 <= b;    // 1
  printf(" 결괏값은 %d 이다.\n", result);
 
  result = a == 10;    // 1
  printf(" 결괏값은 %d 이다.\n", result);
 
  result = a + b == c;   // 1
  printf(" 결괏값은 %d 이다.\n", result);
 
  result = b!= a;    // 1
  printf(" 결괏값은 %d 이다.\n", result);
 
 ★ result = c < b < a;   // 1
  printf(" 결괏값은 %d 이다.\n", result);
 
 ★ result = c > b > a;   // 0
  printf(" 결괏값은 %d 이다.\n", result);
 
  
}
cs

 

4) 논리 연산자 : 두 개의 논리 값을 연산하여 (True) 또는 거짓(False)의 결과를 얻는다.

 여러 개의 조건을 동시에 결합하여 판정하는 연산자로 OR, AND, NOT의 논리 연산을 수행한다.

  관계 연산자와 마찬가지로 참(True)일 때에는 "1", 거짓 (False)일 때에는 "0"으로 표시한다.

 

(조건A) || (조건B)   // 조건 A와 조건 B 중 둘 중 하나가 참이면 1 
(조건A) && (조건B) // 조건 A와 조건 B 중 둘 다 참이면 1 , 하나라도 거짓이면 0  
(조건A) ! (조건B) // 조건 B가 참이면 A는 0, B가 거짓이면 A는 1 
 #include <stdio.h>
int main(){
 
  int A = 10, B = 20, C = 30, result;
 
  result = ( A > B) || ( C > B);
  printf("결괏값은 %d 이다.\n", result); // 결괏값 1
 
  result = ( A > B ) && ( C > B);
  printf("결괏값은 %d 이다.\n", result); // 결괏값 0
 
  result = ! (A > B);
  printf("결괏값은 %d 이다.\n", result); // 결괏값 1
  
}
cs

 

5) 비트 연산자 : 컴퓨터에 숫자가 저장되는 최소 단위인 비트(0,1)별로 연산하여 결과를 얻는다.

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

지금까지 자료형을 바이트 단위로 구분하여 사용했는데, 

비트 연산자는 바이트 단위보다 더 작은 비트 단위로 연산하는 연산자이다.

- 비트(Bit) : 2진수를 저장하는 단위, 컴퓨터에서 사용할 수 있는 최소 단위이며 0과 1을 나타낸다.

- 바이트(Byte) : 8비트 크기의 단위이다.

 

비트 연산자는 비트로 옵션을 설정할 때 주로 사용하며 저장 공간을 아낄 수 있는 장점이 있다.

특이 이런 방식을 플래그(Flag)라고 부른다.

 

(참고) ※  플래그란?

플래그(Flag)는 깃발에서 유래한 용어이다.

보통 깃발을 위로 들어올리면 ON, 아래로 내리면 OFF를 뜻한다.

이걸 정수의 비트에 활용하여 비트가 1이면 ON, 0이면 OFF를 나타낸다.

 

int와 같은 4바이트의 크기의 자료형은 몇 가지의 상태를 저장할 수 있을까?

4바이트는 32비트이므로 32개의 상태를 저장할 수 있다.

 

왜 플래그를 사용할까? 

그냥 int형 변수를 선언해서 각각 상태를 저장하면 될텐데 굳이 플래그를 사용하는 이유는 뭘까?

플래그는 적은 공간에 정보를 저장해야 하고, 빠른 속도가 필요할 때 사용한다.

가장 대표적인 장치가 CPU인데, CPU는 내부 저장 공간이 매우 적기 때문에 각종 상태를 비트로 저장한다.

#include <stdio.h>
int main(){
 
  int A = 10, B = 20, result;
 
  result = A | B;
  printf("결괏값은 %d 이다.\n", result); // 결괏값 30
 
  result = A & B;
  printf("결괏값은 %d 이다.\n", result); // 결괏값 0
  
  result = A ^ B;
  printf("결괏값은 %d 이다.\n", result); // 결괏값 30
 
  result = ~A;
  printf("결괏값은 %d 이다.\n", result); // 결괏값 -11
 
  result = ~B;
  printf("결괏값은 %d 이다.\n", result);
}
cs

1) OR 연산자

- 두 개의 비트 중 하나라도 1이면 1을 반환하는 연산

위에 OR 결괏값을 보면 30이다. 왜 30으로 나올까?

 

A : 00000000 00000000 00000000 00001010

B : 00000000 00000000 00000000 00010100

 

답 : 00000000 00000000 00000000 00011110 = 30

 

A의 비트와 B의 비트 중 하나라도 1이면, 1을 반환한다.

 

2) AND 연산자

- A의 비트와 B의 비트가 모두 1이여야만 1을 반환한다.

 

OR연산자의 비트값을 보면 서로 일치하는 값이 하나도 없는게 눈에 보인다. 그러므로 답은 0

 

3) XOR 연산자 ( ^ )

- ^ 연산은 두 개의 비트가 서로 다른 경우에 1을 반환한다.

 

노린건 아닌데.. 두 개의 비트가 위에 보는것처럼 일치하는게 없다.  답은 OR과 동일하게 30이다.

 

 

4) NOT 연산자 ( 1의 보수)

- ~ 연산은 비트를 0에서 1로, 1에서 0으로 반전하는 연산이다. 보수연산이라고도 불린다.

 

A : 00000000 00000000 00000000 00001010 = (10)

 

답 : 1111111 1111111 1111111 11110101     

첫 비트인 부호 비트가 1이기 때문에 음수이다. 그러므로 답은 -11이다.

 

B : 00000000 00000000 00000000 00010100 = (20)

 

답 : 1111111 1111111 1111111 11101011 

첫 비트인 부호 비트가 1이기 때문에 음수이다. 그러므로 답은 -21이다.

 

다음은 시프트 연산에 대해 알아보자.

 #include <stdio.h>
int main(){
 
  int A = 10,  result;
  
  result = A << 1;
  printf("결괏값은 %d 이다.\n", result); // 결괏값 20
 
  result = A << 2;
  printf("결괏값은 %d 이다.\n", result); // 결괏값 40
 
  result = A << 3;
  printf("결괏값은 %d 이다.\n", result); // 결괏값 80
 
  result = A >> 1;
  printf("결괏값은 %d 이다.\n", result);
  
  result = A >> 2;
  printf("결괏값은 %d 이다.\n", result);
 
  result = A >> 3;
  printf("결괏값은 %d 이다.\n", result);
}
cs

 

1) << 연산자 (비트의 왼쪽 이동)

- A << B  , A의 비트 열을 B칸씩 왼쪽으로 이동시킨 결과를 반환

- 왼쪽으로 밀려나는 비트들은(4바이트 초과) 그냥 버려진다.

 

A의 값을 10으로 대입 후 왼쪽으로 1칸 이동 시

0000 1010 (10) → 0001 0100 (20)

 

A의 값을 10으로 대입 후 왼쪽으로 2칸 이동 시

0000 1010 (10) → 0010 1000 (40)

 

A의 값을 10으로 대입 후 왼쪽으로 3칸 이동 시

0000 1010 (10) → 0101 0000 (80)

 

이 결과로 알 수 있는 사실은 비트의 열을 왼쪽으로 1칸씩 이동시킬 때마다 정수의 값은 두 배가 된다.

 

2) >> 연산자 (비트의 오른쪽 이동)
- A >> B, A의 비트 열을 B칸씩 오른쪽으로 이동시킨 결과를 반환

- 오른쪽으로 밀려나는 비트들은 그냥 버려진다.

 

A의 값을 10으로 대입 후 오른쪽으로 1칸 이동 시

0000 1010 (10) → 0000 0101 (5)

 

A의 값을 10으로 대입 후 오른쪽으로 2칸 이동 시

0000 1010 (10) → 0000 0010 (2)

 

A의 값을 10으로 대입 후 오른쪽으로 3칸 이동 시

0000 1010 (10) → 0000 0001 (1) 

 

이 결과로 알 수 있는 사실은 비트의 열을 오른쪽으로 1칸씩 이동시킬 때마다 정수의 값은 2로 나누어진다.

 

여기까지 연산자 포스팅을 마무리합니다.