본문으로 건너뛰기

연산자

개요​

조건·산술·관계·논리·비트 연산자, 우선순위와 결합 방향.

조건 연산자 (Conditional Operator)​

C 언어에서 유일하게 3개의 **Operand(피연산자)**를 갖는 삼항 연산자이다. 이 연산자는 ?와 : 두 개의 기호로 구성된다.

문법: exp1 ? exp2 : exp3

  • exp1이 참(0이 아닌 값)으로 평가되면, 전체 연산식의 결과는 exp2의 값이 된다.
  • exp1이 거짓(0)으로 평가되면, 전체 연산식의 결과는 exp3의 값이 된다.

예를 들어, max = (a > b) ? a : b; 문장은 a가 b보다 크면 max에 a를, 그렇지 않으면 b를 할당한다. 이는 if-else 문을 간결하게 표현하는 방법이다.

비트 논리 연산자 (Bitwise Logical Operators)​

**Bitwise Logical Operator(비트 논리 연산자)**는 정수 값을 비트 단위로 논리 연산을 수행하는 연산자이다.

연산자기호의미
AND&두 피연산자의 각 비트에 대해 AND 연산을 수행한다.
OR``
XOR^두 피연산자의 각 비트에 대해 XOR 연산을 수행한다 (두 비트가 다를 때 1).
Complement~단일 피연산자의 모든 비트를 반전시킨다 (1의 보수).

비트 연산 진리표:

| 비트 x | 비트 y | x & y | x | y | x ^ y | ~x | | -------- | -------- | ------- | ------- | ------- | ---- | | 0 | 0 | 0 | 0 | 0 | `` | | 0 | 1 | 0 | 1 | 1 | 1 | | 1 | 0 | 0 | 1 | 1 | 0 | | 1 | 1 | 1 | 1 | 0 | 0 |

예를 들어, 3 & 5 연산은 각 숫자의 32비트 이진수 표현에 대해 비트별 AND 연산을 수행한다. 3(00...011)과 5(00...101)를 AND 연산하면 1(00...001)이 된다.

이동 연산자 (Shift Operators)​

**Shift Operator(이동 연산자)**는 변수의 비트들을 지정된 횟수만큼 왼쪽 또는 오른쪽으로 이동시킨다.

연산자기호의미
왼쪽 이동<<비트를 왼쪽으로 이동시킨다.
오른쪽 이동>>비트를 오른쪽으로 이동시킨다.
  • 왼쪽 이동 (<<): 비트들을 왼쪽으로 이동시키고, 왼쪽 경계를 벗어나는 비트는 버려진다. 오른쪽의 빈자리는 모두 0으로 채워진다. a << b 연산은 a에 2^b를 곱하는 효과와 같다.
  • 오른쪽 이동 (>>): 비트들을 오른쪽으로 이동시키고, 오른쪽 경계를 벗어나는 비트는 버려진다. 왼쪽의 빈자리는 원래 숫자의 부호 비트(최상위 비트)로 채워진다. 만약 피연산자가 양수라면 a >> b 연산은 a를 2^b로 나누는 효과와 같다.

비트 마스크 (Bit Mask)​

**Bit Mask(비트 마스크)**는 특정 비트들만 선택하거나 변경하기 위해 사용하는 상수나 변수이다.

  • 특정 비트 값 확인: 확인하려는 비트 위치만 1이고 나머지는 0인 마스크를 만들어 & 연산을 수행한다. 예를 들어, 변수 a의 n번째 비트를 확인하는 일반식은 (a & (1 << (n-1)))이다.
  • 특정 비트 값 변경:
    • 비트를 1로 설정: | 연산을 사용한다.
    • 비트를 0으로 설정: 해당 비트만 1인 마스크를 ~로 반전시킨 후 & 연산을 사용한다.
    • 비트 반전(toggle): ^ 연산을 사용한다.

기타 연산자​

sizeof 연산자​

sizeof는 변수나 자료형이 메모리에서 차지하는 크기를 바이트 단위로 반환하는 연산자이다. sizeof(자료형) 또는 sizeof 변수명 형태로 사용하며, 자료형에는 괄호가 필수이다.

형변환 연산자 (Type Casting)​

C언어는 연산 시 자료형이 다른 피연산자들을 하나의 통일된 자료형으로 자동 변환한다. 크기가 작은 형에서 큰 형으로 변환되는 것을 **Promotion(형 넓히기)**이라고 한다.

반대로, 큰 형에서 작은 형으로 변환(형 좁히기)할 때는 정보 손실이 발생할 수 있다. Type Casting(형변환) 연산자 (자료형)를 사용하여 명시적으로 자료형을 변환할 수 있다.

int x = 6, y = 4;
double result;
result = (double)x / y; // result는 1.5가 된다. x를 double로 형변환 후 나눗셈 수행.
result = x / y; // result는 1.0이 된다. 정수 나눗셈 후 결과를 double로 저장.

축약 대입 연산자 (Compound Assignment Operator)​

+=, -=, *= 등은 산술/비트 연산과 대입 연산을 결합한 형태이다. 예를 들어, x += y는 x = x + y와 동일한 의미를 가진다.

콤마 연산자 (Comma Operator)​

콤마 연산자는 우선순위가 가장 낮다. 왼쪽에서 오른쪽으로 연산을 수행하며, 전체 연산식의 결과값은 가장 마지막에 수행된 연산의 결과가 된다.

  • x = 3+4, 5-10;: 대입 연산자가 콤마보다 우선순위가 높아 x = 7이 먼저 수행되고, 5-10은 의미 없는 구문이 된다.

  • x = (3+4, 5-10);: 괄호 안의 콤마 연산자가 먼저 수행된다. 3+4가 수행된 후 5-10이 수행되고, 마지막 결과인 -5가 x에 대입된다.

연산자 우선순위​

C 언어의 연산자는 정해진 **Operator Precedence(연산자 우선순위)**에 따라 평가된다. 일반적으로 우선순위는 다음과 같다:

  1. 괄호 (), 배열 [], 구조체 . ->
  2. 단항 연산자 (++, --, !, ~, sizeof)
  3. 산술 연산자 (*, /, %, +, -)
  4. 이동 연산자 (<<, >>)
  5. 관계 연산자 (<, >, <=, >=)
  6. 등가 연산자 (==, !=)
  7. 비트 논리 연산자 (&, ^, |)
  8. 논리 연산자 (&&, ||)
  9. 조건 연산자 (?:)
  10. 대입 연산자 (=, +=, -=, 등)
  11. 콤마 연산자 (,)

조건문

조건문은 특정 조건을 만족할 때만 해당하는 코드를 실행하도록 제어하는 문장이다.

if 문​

**if statement(if 문)**는 주어진 표현식(expression)이 참(0이 아닌 값)일 경우에만 뒤따르는 문장(statement)을 실행한다. 여러 문장을 실행하려면 중괄호{}로 묶어야 한다.

if (grade >= 4.3) {
printf("장학금을 받습니다.\n");
}

if-else 문​

else 키워드를 사용하면 if문의 표현식이 거짓일 경우 실행할 문장을 지정할 수 있다.

if (number % 2 == 0) {
printf("짝수(even) 입니다.\n");
} else {
printf("홀수(odd) 입니다.\n");
}

중첩된 if 와 else if 문​

중첩된 if 문은 if문 내부에 또 다른 if문이 포함된 구조이다. 이 때 else는 자신과 가장 가까운 if와 연결되므로, 의도치 않은 동작을 피하기 위해 중괄호{}를 명확히 사용하는 것이 중요하다.

여러 조건을 순차적으로 검사할 때는 else if 구조를 사용하는 것이 더 명확하다.

if (point >= 90) {
printf("학점은 A입니다.\n");
} else if (point >= 80) {
printf("학점은 B입니다.\n");
} else {
printf("학점은 C 이하입니다.\n");
}

switch 문​

switch문은 하나의 정수 표현식 값에 따라 여러 경로 중 하나를 선택하여 실행하는 다중 선택문이다. if-else if 구조보다 코드가 간결해질 수 있다.

  • switch (expression): expression은 반드시 정수형으로 평가되어야 한다.

  • case value:: expression의 결과값과 value(정수 상수)가 일치하면 해당 case의 문장부터 실행된다.

  • break: switch 블록을 즉시 빠져나간다. break가 없으면 일치하는 case 이후의 모든 case 문장들이 순차적으로 실행된다(fall-through). 이를 이용해 여러 case

    에 대해 동일한 코드를 실행시킬 수 있다.

  • default: 어떤 case와도 일치하지 않을 때 실행된다.

윤년 계산 예시: switch문과 if문을 활용하여 특정 년도의 월별 마지막 날을 계산할 수 있다. 2월의 경우, 윤년을 판별하는 로직이 필요하다. 윤년의 조건은 다음과 같다:

  • 4로 나누어 떨어지면서 100으로 나누어 떨어지지 않는 해
  • 또는 400으로 나누어 떨어지는 해
  • ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)