C/Chapter04. 수식과 연산자

lullaby ·2025년 10월 1일

C언어

목록 보기
4/10
post-thumbnail

1. 핵심 개념 정리

수식의 기본 개념

  • 수식(expression): 연산자와 피연산자의 조합으로, 값을 갖는 요소
  • 연산자(operator): 연산에 사용되는 기호 (예: +, -, *, /)
  • 피연산자(operand): 연산의 대상이 되는 값

연산자의 분류

  1. 피연산자 개수에 따른 분류:
    • 단항 연산자: 피연산자가 1개 (예: ++x, -y, !x)
    • 이항 연산자: 피연산자가 2개 (예: x+y, x*y, x>=y)
    • 삼항 연산자: 피연산자가 3개 (예: x?y:z)
  2. 기능에 따른 분류:
    • 산술 연산자: +, -, *, /, %
    • 증감 연산자: ++, --
    • 관계 연산자: >, <, >=, <=, ==, !=
    • 논리 연산자: &&, ||, !
    • 비트 연산자: &, |, ^, ~, <<, >>
    • 대입 연산자: =, +=, -=, *=, /= 등
    • 조건 연산자: ? :
    • 형변환 연산자: (type)

산술 연산자

  • 기본 사칙 연산: +, -, *, /, %
  • 정수 나눗셈의 경우 몫은 정수 (소수점 버림)
  • 나머지 연산자(%): 피연산자가 모두 정수인 경우에만 사용

증감 연산자

  • 전위형(++x, --x): 변수 값을 증가/감소시킨 후 수식 평가
  • 후위형(x++, x--): 수식 평가 후 변수 값 증가/감소
  • 상수나 수식에는 사용 불가 (변수에만 사용)

대입 연산자

  • 기본 대입 연산자(=): 우변의 값을 좌변에 저장
  • 좌변에는 lvalue(변수)만 올 수 있음
  • 복합 대입 연산자: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=

관계 연산자

  • 두 값을 비교하는 연산자: >, <, >=, <=, ==, !=
  • 연산 결과는 참(1) 또는 거짓(0)
  • 주의: 동등 비교는 ==, 대입은 =

논리 연산자

  • 논리 AND(&&): 두 피연산자가 모두 참이면 참
  • 논리 OR(||): 두 피연산자 중 하나라도 참이면 참
  • 논리 NOT(!): 피연산자가 참이면 거짓, 거짓이면 참

비트 연산자

  • 비트 AND(&): 대응되는 비트가 모두 1이면 1
  • 비트 OR(|): 대응되는 비트 중 하나라도 1이면 1
  • 비트 XOR(^): 대응되는 비트가 서로 다르면 1
  • 비트 NOT(~): 모든 비트를 반전
  • 왼쪽 시프트(<<): 비트를 왼쪽으로 이동 (x << n은 x * 2^n)
  • 오른쪽 시프트(>>): 비트를 오른쪽으로 이동 (x >> n은 x / 2^n)

조건 연산자

  • 형식: 조건식 ? 참일 때 값 : 거짓일 때 값
  • if-else문을 한 줄로 표현할 수 있음

형변환 연산자

  • 암시적 형변환: 컴파일러가 자동으로 수행
  • 명시적 형변환: (type) 형식으로 프로그래머가 지정

연산자 우선순위와 결합방향

  • 괄호 > 단항 > 산술 > 시프트 > 관계 > 비트 > 논리 > 조건 > 대입 > 콤마
  • 대부분 왼쪽에서 오른쪽으로 결합(→)
  • 단항 연산자와 대입 연산자는 오른쪽에서 왼쪽으로 결합(←)

2. 주요 문법 및 예제 코드

산술 연산자 예제

#include <stdio.h>

int main(void) {
    int a = 10, b = 3;

    printf("a + b = %d\n", a + b);  // 13
    printf("a - b = %d\n", a - b);  // 7
    printf("a * b = %d\n", a * b);  // 30
    printf("a / b = %d\n", a / b);  // 3 (정수 나눗셈)
    printf("a %% b = %d\n", a % b); // 1 (나머지)

    return 0;
}

증감 연산자 예제

#include <stdio.h>

int main(void) {
    int a = 5, b = 5;
    int result1, result2;

    // 전위형
    result1 = ++a; // a를 증가시킨 후 대입
    printf("a = %d, result1 = %d\n", a, result1); // a = 6, result1 = 6

    // 후위형
    result2 = b++; // 대입 후 b를 증가
    printf("b = %d, result2 = %d\n", b, result2); // b = 6, result2 = 5

    return 0;
}

복합 대입 연산자 예제

#include <stdio.h>

int main(void) {
    int x = 10;

    x += 5;  // x = x + 5
    printf("x = %d\n", x);  // 15

    x -= 3;  // x = x - 3
    printf("x = %d\n", x);  // 12

    x *= 2;  // x = x * 2
    printf("x = %d\n", x);  // 24

    x /= 4;  // x = x / 4
    printf("x = %d\n", x);  // 6

    x %= 4;  // x = x % 4
    printf("x = %d\n", x);  // 2

    return 0;
}

관계 및 논리 연산자 예제

#include <stdio.h>

int main(void) {
    int a = 10, b = 20;

    printf("a > b: %d\n", a > b);   // 0 (거짓)
    printf("a < b: %d\n", a < b);   // 1 (참)
    printf("a == b: %d\n", a == b); // 0 (거짓)
    printf("a != b: %d\n", a != b); // 1 (참)

    // 논리 연산자
    printf("a > 5 && b < 30: %d\n", a > 5 && b < 30); // 1 (참 AND 참)
    printf("a > 15 || b < 30: %d\n", a > 15 || b < 30); // 1 (거짓 OR 참)
    printf("!(a > b): %d\n", !(a > b)); // 1 (NOT 거짓)

    return 0;
}

비트 연산자 예제

#include <stdio.h>

int main(void) {
    unsigned char a = 12; // 00001100
    unsigned char b = 10; // 00001010

    printf("a & b = %d\n", a & b);  // 8 (00001000)
    printf("a | b = %d\n", a | b);  // 14 (00001110)
    printf("a ^ b = %d\n", a ^ b);  // 6 (00000110)
    printf("~a = %d\n", ~a);        // 243 (11110011)
    printf("a << 1 = %d\n", a << 1); // 24 (00011000)
    printf("a >> 1 = %d\n", a >> 1); // 6 (00000110)

    return 0;
}

조건 연산자 예제

#include <stdio.h>

int main(void) {
    int a = -10, b = 20;
    int abs_a, max_val;

    // 절대값 구하기
    abs_a = (a < 0) ? -a : a;
    printf("a의 절대값: %d\n", abs_a); // 10

    // 최대값 구하기
    max_val = (a > b) ? a : b;
    printf("a와 b 중 최대값: %d\n", max_val); // 20

    return 0;
}

형변환 예제

#include <stdio.h>

int main(void) {
    int i = 10;
    double d = 3.14;

    // 암시적 형변환
    double result1 = i + d; // int -> double
    printf("i + d = %f\n", result1); // 13.140000

    // 명시적 형변환
    int result2 = (int)d + i; // double -> int
    printf("(int)d + i = %d\n", result2); // 13

    // 나눗셈에서의 형변환
    int x = 10, y = 3;
    double div1 = x / y; // 정수 나눗셈 후 double로 변환
    double div2 = (double)x / y; // 실수 나눗셈

    printf("x / y = %f\n", div1); // 3.000000
    printf("(double)x / y = %f\n", div2); // 3.333333

    return 0;
}

3. 예상 문제 및 풀이

C 프로그래밍 중간고사 예상 문제 및 풀이

객관식 문제

문제 1

다음 중 후위형 증감 연산자(x++, x--)의 특징으로 옳은 것은?

  1. 연산자가 수식에서 사용될 때 변수의 값을 먼저 증가시키고 수식을 평가한다.
  2. 연산자가 수식에서 사용될 때 수식을 평가한 후에 변수의 값을 증가시킨다.
  3. 연산자는 변수뿐만 아니라 상수에도 사용할 수 있다.
  4. 연산자는 다른 연산자보다 항상 우선순위가 낮다.

정답: 2

풀이: 후위형 증감 연산자(x++, x--)는 수식을 평가한 후에 변수의 값을 증가시키거나 감소시킨다. 예를 들어 y = x++;에서는 먼저 x의 값을 y에 대입한 후에 x의 값을 1 증가시킨다.

문제 2

다음 C 코드의 출력 결과는?

int x = 5, y;
y = x++ + ++x;
printf("%d %d", x, y);
  1. 7 11
  2. 7 12
  3. 6 11
  4. 6 12

정답: 1

풀이:

  • y = x++ + ++x에서 연산 순서는 다음과 같다:
  • x++: x의 현재 값 5를 사용한 후, x를 6으로 증가 (후위형)
  • ++x: x를 7로 증가시킨 후, 그 값 7을 사용 (전위형)
  • y = 5 + 7 = 12
  • 최종적으로 x는 7이 되고, y는 12가 된다.
  • 따라서 출력 결과는 7 12

문제 3

다음 중 비트 연산에 대한 설명으로 옳지 않은 것은?

  1. a & b는 a와 b의 대응되는 비트가 모두 1일 때만 1을 반환한다.
  2. a | b는 a와 b의 대응되는 비트 중 하나라도 1이면 1을 반환한다.
  3. a << 2는 a의 각 비트를 왼쪽으로 2칸 이동시키고, 2를 곱한 효과가 있다.
  4. a >> 2는 a의 각 비트를 오른쪽으로 2칸 이동시키고, 2로 나눈 몫의 효과가 있다.

정답: 3

풀이: a << 2는 a의 각 비트를 왼쪽으로 2칸 이동시키는 연산으로, 이는 a에 2^2 = 4를 곱한 효과가 있다(2가 아님). 예를 들어, 5(101) << 2는 20(10100)이 된다.

문제 4

다음 C 코드의 출력 결과는?

int x = 10, y = 5;
printf("%d", x > y ? x : y);
  1. 10
  2. 5
  3. 1
  4. 0

정답: 1

풀이: 조건 연산자 ?:는 조건식이 참일 때 첫 번째 값을, 거짓일 때 두 번째 값을 반환한다. x > y는 참(1)이므로 x의 값인 10이 출력된다.

문제 5

다음 중 C에서 논리 연산자에 관한 설명으로 옳은 것은?

  1. && 연산자는 두 피연산자가 모두 0이 아니면 0을 반환한다.
  2. || 연산자는 두 피연산자 중 하나라도 0이 아니면 해당 피연산자의 값을 반환한다.
  3. ! 연산자는 피연산자가 0이면 1을, 0이 아니면 0을 반환한다.
  4. 논리 연산자의 결과는 항상 정수형이다.

정답: 3

풀이:

  • && 연산자는 두 피연산자가 모두 0이 아니면 1을 반환한다.
  • || 연산자는 두 피연산자 중 하나라도 0이 아니면 1을 반환한다.
  • ! 연산자는 피연산자가 0이면 1을, 0이 아니면 0을 반환한다.
  • 논리 연산자의 결과는 항상 0 또는 1이다.

서술형 문제

문제 6

다음 코드의 실행 결과를 적고, 그 과정을 설명하시오.

int a = 15, b = 20;
int c = a & b;
int d = a | b;
int e = a ^ b;
printf("%d %d %d", c, d, e);

정답: 4 31 27

풀이:

  • a = 15 (1111)
  • b = 20 (10100)
  • c = a & b = 15 & 20 = 00001111 & 00010100 = 00000100 = 4
  • d = a | b = 15 | 20 = 00001111 | 00010100 = 00011111 = 31
  • e = a ^ b = 15 ^ 20 = 00001111 ^ 00010100 = 00011011 = 27

문제 7

다음 코드의 실행 결과를 적고, 각 변수의 값이 어떻게 변화하는지 설명하시오.

int x = 5;
int y = 3;
int z = 2;
x += y -= z;
printf("%d %d %d", x, y, z);

정답: 6 1 2

풀이:

  • 복합 대입 연산자는 오른쪽에서 왼쪽으로 결합한다.
  • 먼저 y -= z가 계산된다: y = y - z = 3 - 2 = 1
  • 그 다음 x += (y -= z)를 계산: x = x + (y - z) = 5 + 1 = 6
  • 최종적으로 x = 6, y = 1, z = 2가 된다.

문제 8

다음 코드의 실행 결과를 적고, 형변환이 어떻게 적용되는지 설명하시오.

int a = 10;
int b = 3;
double result1 = a / b;
double result2 = (double)a / b;
printf("%.2f %.2f", result1, result2);

정답: 3.00 3.33

풀이:

  • result1 = a / b에서 a와 b는 모두 정수형이므로 정수 나눗셈이 수행되어 3이 나온다. 이후 double 형으로 저장되어 3.00이 된다.
  • result2 = (double)a / b에서 a가 명시적으로 double로 형변환되었으므로 a/b는 실수 나눗셈이 수행되어 3.333333...이 나온다. 소수점 둘째 자리까지 출력하므로 3.33이 된다.

코드 작성 문제

문제 9

사용자로부터 6자리 정수를 입력받아 천 단위로 콤마(,)를 찍어 출력하는 프로그램을 작성하시오. (나머지 연산자 사용)

답안:

#include <stdio.h>

int main(void) {
    int num;
    int thousands, rest;

    printf("6자리 정수를 입력하세요: ");
    scanf("%d", &num);

    thousands = num / 1000;
    rest = num % 1000;

    printf("%d,%03d\n", thousands, rest);

    return 0;
}

설명:

  • 입력된 수를 1000으로 나누어 몫(thousands)과 나머지(rest)를 구한다.
  • 출력 시 나머지가 3자리보다 작은 경우에도 3자리를 유지하기 위해 %03d 형식 지정자를 사용한다.

문제 10

비트 연산자를 사용하여 정수의 특정 위치 비트를 1로 설정하는 프로그램을 작성하시오. 사용자로부터 정수와 비트 위치(0~31)를 입력받아 해당 비트를 1로 설정한 후 결과를 출력하시오.

답안:

#include <stdio.h>

int main(void) {
    unsigned int num, pos, result;

    printf("정수를 입력하세요: ");
    scanf("%u", &num);

    printf("설정할 비트 위치(0~31)를 입력하세요: ");
    scanf("%u", &pos);

    if (pos > 31) {
        printf("비트 위치는 0~31 사이여야 합니다.\n");
        return 1;
    }

    // 해당 위치의 비트를 1로 설정
    result = num | (1 << pos);

    printf("원래 수: %u (이진수: ", num);

    // 이진수 출력 (간단한 방법)
    for (int i = 31; i >= 0; i--) {
        printf("%d", (num >> i) & 1);
    }

    printf(")\n");
    printf("결과 수: %u (이진수: ", result);

    for (int i = 31; i >= 0; i--) {
        printf("%d", (result >> i) & 1);
    }

    printf(")\n");

    return 0;
}

설명:

  • 정수와 비트 위치를 입력받는다.
  • 비트 위치가 유효한지 확인한다.
  • 1 << pos로 해당 위치에만 1이 있는 마스크를 생성한다.
  • 원래 수와 마스크를 OR 연산하여 해당 비트를 1로 설정한다.
  • 원래 수와 결과 수를 10진수와 2진수로 출력한다.

0개의 댓글