[C언어] 연산자

라임이·2022년 8월 17일
0

C언어

목록 보기
10/11

해당 C언어 시리즈는 처음 코딩을 접하는 사람들이 쉽게 이해할 수 있도록 작성되었습니다.

연산자

수학에서 값을 연산할 수 있듯이 코딩에서도 값을 연산할 수 있습니다.
수학과 크게 다를 것 없어 어찌 보면 가장 부담 없는 파트로 마음 편히 학습하시면 되겠습니다.

C언어에서 연산자는 다음의 종류로 분류됩니다.

연산자

위의 연산자 말고도 조건(삼항) 연산자, 비트 연산자 등의 다양한 연산자가 존재하지만 해당 내용은 뒷부분에서 필요할 때 설명드리겠습니다.


대입 연산자

int var = 5;

위 코드는 int형 변수 var에 10진 정수 5를 대입하라는 명령문입니다.

= 연산자를 기준으로 왼쪽에 위치한 값(대입의 대상)을 lvalue, 오른쪽에 위치한 값을 rvalue라고 합니다. 대입 연산자는 rvalue를 lvalue에 대입(저장)하는 역할을 합니다.


산술 연산자

산술 연산자는 흔히 수학에서 사용하던 사칙연산과 같습니다.
다른 점이 있다면 나누기를 /(슬래시)로 표현하고, %라는 나머지 연산자가 존재한다는 겁니다.

int var;

var = 5 + 3; // 5와 3을 더한 값을 var에 저장
printf("5 + 3 = %d\n", var);

var = 5 - 3; // 5에 3을 뺀 값을 var에 저장
printf("5 - 3 = %d\n", var);

var = 5 * 3; // 5와 3을 곱한 값을 var에 저장
printf("5 * 3 = %d\n", var);

var = 5 / 3; // 5를 3으로 나눈 값(몫)을 var에 저장
printf("5 / 3 = %d\n", var);

var = 5 % 3; // 5를 3으로 나눈 나머지 값을 var에 저장
printf("5 %% 3 = %d\n", var);
출력: 5 + 3 = 8
5 - 3 = 2
5 * 3 = 15
5 / 3 = 1
5 % 3 = 2

복합 대입 연산자

복합 대입 연산자는 산술 연산자와 대입 연산자를 합쳐 수식을 간단하게 만들어주는 연산자입니다.

int var = 5;

printf("var: %d\n", var);
var = var + 3;
printf("var = var + 3: %d\n", var);

var = var - 3;
printf("var = var - 3: %d\n", var);

var = var * 3;
printf("var = var * 3: %d\n", var);

var = var / 3;
printf("var = var / 3: %d\n", var);

var = var % 3;
printf("var = var %% 3: %d\n", var);
출력: var: 5
var = var + 3: 8
var = var - 3: 5
var = var * 3: 15
var = var / 3: 5
var = var % 3: 2

우리는 변수가 가지고 있는 값을 연산하여 다시 대입할 때 위와 같은 코드를 사용했습니다.

산술 연산자는 대입 연산자보다 연산자 우선순위가 높아 먼저 계산됩니다.
이를 이용하면 두 연산자를 합쳐 다음과 같이 변형된 복합 대입 연산자를 얻을 수 있습니다.

int var = 5;

printf("var: %d\n", var);
var += 3; // var = var + 3;
printf("var += 3: %d\n", var);

var -= 3; // var = var - 3;
printf("var -= 3: %d\n", var);

var *= 3; // var = var * 3;
printf("var *= 3: %d\n", var);

var /= 3; // var = var / 3;
printf("var /= 3: %d\n", var);

var %= 3; // var = var % 3;
printf("var %%= 3: %d\n", var);
출력: var: 5
var += 3: 8
var -= 3: 5
var *= 3: 15
var /= 3: 5
var %= 3: 2

앞에서 말했듯이 산술 연산자의 실행 후 대입 연산자가 실행되기 때문에 동일한 결괏값을 얻을 수 있습니다.


증감 연산자

증감 연산자는 증가 또는 감소를 시키는 연산자입니다.
증감 연산자는 ++과 --가 있고 위치에 따라 전위형(prefix)후위형(postfix)으로 구분됩니다.

int var = 5;

printf("%d, ", var);
var++;
printf("%d, ", var);

++var;
printf("%d, ", var);

var--;
printf("%d, ", var);

--var;
printf("%d\n", var);
출력: 5, 6, 7, 6, 5

위 코드와 같이 증감 연산자는 변수의 앞 또는 뒤에 사용할 수 있습니다.
위치에 관계없이 ++을 붙이면 값이 1 증가하고, --를 붙이면 값이 1 감소합니다.

그렇다면 위치에 따라 구분되는 전위형과 후위형은 어떠한 차이가 있을까요?

int var = 5;

printf("%d, ", var);   // var의 값을 출력(5)
printf("%d, ", ++var); // var의 값을 1 증가(6)시킨 뒤 출력(6)
printf("%d\n", var);   // var의 값을 출력(6)

printf("%d, ", var++); // var의 값을 출력(6)한 뒤 1 증가(7)
printf("%d\n", var);   // var의 값을 출력(7)

printf("%d, ", --var); // var의 값을 1 감소(6)시킨 뒤 출력(6)
printf("%d\n", var);   // var의 값을 출력(6)

printf("%d, ", var--); // var의 값을 출력(6)한 뒤 1 감소(5)
printf("%d\n", var);   // var의 값을 출력(5)
출력: 5, 6, 6
6, 7
6, 6
6, 5

전위형은 값의 연산을 먼저 진행하고 해당 명령줄의 명령을 수행합니다.
반면, 후위형은 해당 명령줄의 명령을 먼저 진행하고 연산을 수행합니다.

한마디로 연산을 먼저 하느냐(전위형), 명령줄의 명령을 먼저 실행하느냐(후위형)의 차이입니다.

산술 연산자와 증감 연산자의 비교

int var = 5;
var = var + 1; // 산술 연산자
var++; // 증가 연산자

산술 연산자는 2개의 항을 필요로 하는 이항 연산자입니다.
반면, 증감 연산자는 1개의 항만을 필요로 하는 단항 연산자입니다.

컴파일러가 기계어로 번역하는 과정에서
덧셈을 하는 산술 연산자는 CPU에서 ADD라는 명령어로 바뀌고,
증가 연산자는 INC(Increment)라는 명령어로 바뀝니다.

또한 산술 연산자는 이항 연산자이기 때문에 메모리 2개가 연산에 사용되고,
증가 연산자는 단항 연산자이기 때문에 한 개의 메모리만 연산에 사용됩니다.

위의 내용을 통해 두 연산자는 동일한 기능을 수행하지만 다른 명령어이고, 메모리를 적게 사용하는 증감 연산자의 속도가 더 빠르다는 사실을 알 수 있습니다.

따라서 우리는 앞으로 1을 증가, 또는 감소시키는 명령을 사용할 때 주로 증감 연산자를 이용할 겁니다.


관계 연산자

관계 연산자는 두 값(데이터)을 비교하는 연산자입니다.
관계 연산자 역시 산술 연산자처럼 수학과 매우 비슷합니다.

<, >, <=, >=, ==, !=로 왼쪽의 값과 오른쪽의 값의 대소 크기 비교, 일치 여부를 확인합니다.

다음은 각 연산자의 의미입니다.

  • a < b: a가 b보다 작은가
  • a > b: a가 b보다 큰가
  • a <= b: a가 b보다 작거나 같은가
  • a >= b: a가 b보다 크거나 같은가
  • a == b: a와 b가 같은가
  • a != b: a와 b가 다른가

관계 연산자는 참일 경우 1, 거짓일 경우 0의 값을 반환합니다.

int a = 3, b = 5;

printf("a(3) < b(5): %d\n", a < b);
printf("a(3) > b(5): %d\n", a > b);
printf("a(3) <= b(5): %d\n", a <= b);
printf("a(3) >= b(5): %d\n", a >= b);
printf("a(3) == b(5): %d\n", a == b);
printf("a(3) != b(5): %d\n", a != b);
출력: a(3) < b(5): 1
a(3) > b(5): 0
a(3) <= b(5): 1
a(3) >= b(5): 0
a(3) == b(5): 0
a(3) != b(5): 1

주의사항 1. 대입 연산자 =과 관계 연산자 ==의 혼용

수학에서는 ==라는 연산이 없고 =라는 연산만을 사용하기 때문에 코딩을 접한 지 얼마 안 된 프로그래머들이 두 연산자를 혼용하는 실수를 범합니다.

=는 lvalue에 rvalue를 대입,
==는 lvalue와 rvalue의 값이 같은지 비교하는 연산자임을 꼭 기억합시다.


논리 연산자

컴퓨터 공학에서 일반적으로 논리라 함은 AND, OR, NOT 등을 의미합니다.
논리 연산자는 AND, OR, NOT의 연산을 해주는 연산자라고 보면 됩니다.

다음은 각 연산자의 의미입니다.

  • a && b: a 그리고 b이면 참(AND)
  • a || b: a 또는 b이면 참(OR)
  • !a: a의 부정, a가 참일 경우 거짓, 거짓일 경우 참으로 만듦(반전)

논리 연산자 역시 참이면 1, 거짓이면 0을 반환합니다.

&& 연산자는 a와 b가 모두 참이어야 논리적으로 참이 되므로 두 조건(a, b)을 모두 확인합니다.

|| 연산자는 a 또는 b 중 하나 이상 참이면 논리적으로 참이 되므로 a || b에서 a가 참이라면 b는 확인하지 않습니다. 반대로 a가 거짓일 경우에는 b를 확인합니다.

int a = 3, b = 5;

printf("a(3) < b(5) && a == 3: %d\n", a < b && a == 3);   // a가 b보다 작고(AND), a가 3인가
printf("a(3) > b(5) && a == 3: %d\n", a > b && a == 3);   // a가 b보다 크고(AND), a가 3인가
printf("a(3) <= b(5) || a == 3: %d\n", a <= b || a == 3); // a가 b보다 작거나 같거나(OR), a가 3인가
printf("a(3) >= b(5) || a == 3: %d\n", a >= b || a == 3); // a가 b보다 크거나 같거나(OR), a가 3인가
printf("!a(3): %d\n", !a);                                // a의 부정 | 참일 경우 거짓, 거짓일 경우 참
printf("!b(5): %d\n", !b);                                // b의 부정 | 참일 경우 거짓, 거짓일 경우 참
출력: a(3) < b(5) && a == 3: 1
a(3) > b(5) && a == 3: 0
a(3) <= b(5) || a == 3: 1
a(3) >= b(5) || a == 3: 1
!a(3): 0
!b(5): 0

C언어에서 거짓은 0으로 표현하고, 0을 제외한 모든 값을 참으로 표현하기 때문에 a와 b를 부정하면 거짓이 되어 0이 출력됩니다.

profile
백엔드 개발이 즐거운 4학년 컴공생

0개의 댓글