본문 바로가기

Programming Language/C

연산자

1. 연산자와 피연산자의 개념

연산자(Operator) 는 연산을 수행하는 기호를 의미하고, 피연산자(Operand) 는 연산에 포함되는 변수나 상수를 의미합니다.
A+B를 예로 들어보면 AB는 피연산자에 해당하며 + 는 연산자에 해당하는 것입니다.

1.1. 이스케이프 시퀀스(Escape Sequence)

연산자의 종류에 대해서 하나씩 알아보기 전에 잠시 이스케이프 시퀀스에 대해 짚고 넘어가겠습니다. 사실 이스케이프 시퀀스는 간단한 코드를 앞에서 먼저 다루면서 자연스럽게 자주 사용했습니다. 예를 들어 아래와 같은 코드를 프로그램 안에서 자주 보았을 것입니다. 아래의 코드에서 \n은 줄바꿈의 역할을 합니다.

printf("%d\n", a > b);

이 외에도 다양한 이스케이프 시퀀스가 존재합니다.

이스케이프 시퀀스 기능
\n 줄 바꾸기
\t 수평 탭 넣기
\ 백슬래시 넣기
" 큰 따옴표 넣기
\b 백스페이스 넣기

예제1

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void) {
    printf("\"A B C D\"\n");
    printf("\"A\t B\t C\t D\"\n");
    printf("\"A\t B\t C\t D\"\n\n");
    system("pause");
}

결과:

예제2

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void) {
    printf("\"A B\b C D\"\n");
    printf("\"A\t B\t C\t D\"\n");
    printf("\"A\t B\t C\t D\"\n\n");
    system("pause");
}

결과:


2. 연산자의 종류

C언어에는 다양한 연산자가 존재합니다.

연산자의 종류 연산 부호
대입 연산자 =
산술 연산자 +, -, *, /, %
관계 연산자 ==, !=, >, <, >=, <=
논리 연산자 !, &&,
증감 연산자 ++, --
삼항 연산자 ? :
비트 연산자 !, ~, &, ^, >>, <<

2.1. 대입 연산자

대입 연산자는 '=' 등호를 사용해서 자료형에 부합하는 우변항의 값을 좌변항에 있는 변수에 넣을 수 있습니다. 일반적으로 사용하는 '같다'의 의미와는 다릅니다.

2.2. 산술 연산자(사칙 연산)

C언어에서는 기본적인 사칙 연산을 사용할 수 있습니다. 더하기, 빼기, 곱하기는 일반적인 계산과 다름이 없으나 나누기 연산은 몫만 계산합니다. 나머지를 구하고 싶을 때는 모듈러 연산( % )을 사용합니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// 사칙연산
int main(void) {
    int a, b;
    scanf("%d%d", &a, &b);
    printf("%d + %d = %d\n", a, b, a + b);
    printf("%d - %d = %d\n", a, b, a - b);
    printf("%d * %d = %d\n", a, b, a * b);
    printf("%d / %d = %d\n", a, b, a / b);
    printf("%d %% %d = %d\n", a, b, a % b);
    system("pause");
}

결과:

5
2
5 + 2 = 7
5 - 2 = 3
5 * 2 = 10
5 / 2 = 2
5 % 2 = 1
계속하려면 아무 키나 누르십시오 . . .

2.3. 관계 연산자

관계연산자 의미
> 크다
< 작다
== 같다
!= 다른지 물어보는 관계연산자로 !는 not의 의미를 지닌다
>= 크거나 같다
<= 작거나 같다

컴퓨터는 0을 거짓(False)으로 받아들이고, 그 외의 숫자를 참(True)으로 받아들인다. 0만 아니라면 참으로 인식한다고 할 수 있습니다. 따라서, 컴퓨터가 거짓을 출력할 때는 0을 출력하고, 참을 출력할 때는 1을 출력합니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void) {
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d\n", a > b);
    printf("%d\n", a != b);
    system("pause");
}

결과:

5 2
1
1
계속하려면 아무 키나 누르십시오 . . .

2.4. 논리 연산자

2.4.1. !

부정 의 뜻을 가지며, 참을 거짓으로 바꿉니다.

2.4.2. &&

'그리고' 의 뜻을 가집니다.
(수식A) && (수식B)를 예로 들 때, 하나라도 거짓이라면 결과는 거짓입니다.
참 && 참 == 참
참 && 거짓 == 거짓

2.4.3. ||

'또는' 의 뜻을 가집니다.
(수식A) || (수식B)를 예로 들 때, 하나라도 참이라면 결과는 참입니다.
거짓 || 거짓 == 거짓
거짓 || 참 == 참

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    printf("%d\n", !a);
    printf("%d\n", a && b);
    printf("%d\n", (a > b) && (b > c));
    system("pause");
    return 0;
}

결과:

2 1 3
0
1
0
계속하려면 아무 키나 누르십시오 . . .

2.5. 증감 연산자

증감연산자 특징
++(변수) i의 값을 1증가시킨 후에 증가된 값을 반환
(변수)++ i의 값을 1증가시킨 후에 증가되기 전의 값을 반환
--(변수) i의 값을 1감소시킨 후에 감소된 값을 반환
(변수)-- i의 값을 1감소시킨 후에 감소되기 전의 값을 반환
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void) {
    int a = 7;
    printf("%d\n", ++a);
    printf("%d\n", a++);
    printf("%d\n", ++a);
    system("pause");
    return 0;
}

결과:

8
8
10
계속하려면 아무 키나 누르십시오 . . .

2.6. 삼항 연산자

삼항 연산자는 세 개의 항을 이용해서 조건문을 수행할 수 있는 연산자입니다. 즉, 조건을 파악해서 프로그램의 진행경로를 바꿀 수 있는 연산자인 것입니다. 형식은 다음과 같습니다.
(수식 A) ? a : b
수식 A의 결과가 참이라면 a를 반환하고 거짓이라면 b를 반환합니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void) {
    int a = 7, b = 8;
    printf("%d\n", (a == b) ? 100 : -100);
    system("pause");
    return 0;
}

결과:

-100
계속하려면 아무 키나 누르십시오 . . .

2.7. 비트 연산자

비트 연산자는 비트 단위의 연산을 수행할 수 있는 연산자입니다.

2.7.1. ~ (부정, not)

각각의 자리 수를 모두 비교해서 0인 것은 1로, 1인 것은 0으로 반전시킵니다.

~(11000011)2 = (00111100)2

2.7.2 & (그리고, and)

왼쪽 값과 오른쪽 값의 자리 수를 각각 모두 비교해 둘 다 1인 것만 1로 해당 자리에 표기합니다.

(00001101)2 & (00000011)2 = (00000001)2
위 예시에서는 20 자리가 동일하게 1이기 때문에 20 자리만 1로 표시한 결과를 얻습니다.

2.7.3. | (또는, or)

or연산에서는 and연산에서와 마찬가지로 각 자리 수를 모두 비교햇을 때 둘 중 하나라도 1을 가지면 1로 표기합니다.

(11001100)2 | (00110000)2 = (11111100)2

2.7.4. ^ (배타적)

둘 중 하나만 1일 때 결과로 1이 나옵니다. 둘 다 1일 경우에는 0으로 출력합니다.

(11001111)2 ^ (00000011)2 = (11001100)2

2.7.5. << (왼쪽 시프트, shift)

비트를 한 번에 옮길 때 사용합니다.

(00001111)2 << 3 = (01111000)2
위 예시와 같이 시프트 문자 오른쪽에 있는 3이라는 숫자는 8비트라는 공간 안에서 20의 자리에서부터 왼쪽으로 3칸만큼 밀어낸다는 것을 의미합니다.
왼쪽 시프트가 있듯이 오른쪽 시프트 또한 존재합니다. 표기는 >> 입니다.

shift연산자는 2의 배수를 처리하고자 할 때 효과적입니다. 9를 8비트 공간에서 2진수로 표현하면 다음과 같습니다.
0 0 0 0 1 0 0 1
이 상태에서 왼쪽 shift를 한 번 실행하면 9에서 18로 2배가 증가하게 됩니다.
0 0 0 1 0 0 1 0
위의 2진수를 10진수로 계산해보면 (21 * 1) + (24 * 1) = 2 + 16 = 18
정확히 2배가 증가한 값이 나옵니다.

왼쪽으로 1번 shift를 실행했을 때 2배가 되었듯이, 반대로 오른쪽으로 1번 shift를 실행하면 2로 나눈 값이 반환됩니다.


3. 연산자 우선순위

C언어의 연산자 우선순위는 수학에서의 연산 우선순위와 흡사합니다.

우선순위 연산자
1 ++, --
2 !, ~
3 *, /, %
4 +, -
5 <<, >>
6 <, <=, >, >=
7 ==, !=
8 비트, 논리, 삼항 연산자

훨씬 자세한 연산자 우선순위는 코딩도장의 C언어 강의를 참고하는 것이 좋을 듯 합니다.