Menu
Coddy logo textTech

Const 정확성

Coddy C 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 8번째.

메서드 역할을 하는 함수를 작성할 때, 일부는 객체를 수정해야 하지만(player_take_damage와 같이), 다른 것들은 아무것도 변경하지 않고 데이터만 읽어야 합니다. const 키워드를 사용하면 컴파일러 수준에서 이러한 구분을 강제할 수 있습니다.

포인터 매개변수를 const로 표시함으로써, 해당 함수가 가리키는 데이터를 수정하지 않겠다고 약속하는 것입니다. 실수로 멤버를 변경하려고 시도하면, 컴파일러가 오류를 발생시킵니다:

typedef struct {
    int x;
    int y;
} Point;

// 이 함수는 point를 읽기만 할 수 있습니다
void point_print(const Point *self) {
    printf("(%d, %d)\n", self->x, self->y);
    // self->x = 10;  // 오류: const 포인터를 통해 수정할 수 없습니다
}

// 이 함수는 point를 수정할 수 있습니다
void point_move(Point *self, int dx, int dy) {
    self->x += dx;
    self->y += dy;
}

const Point *self 매개변수는 컴파일러와 다른 프로그래머 모두에게 point_print가 "게터(getter)" 또는 읽기 전용 작업임을 알려줍니다. 이것을 상수성 유지(const correctness)라고 하며, 수정이 필요하지 않은 모든 곳에 const를 사용하는 것을 의미합니다.

이러한 관행은 버그를 조기에 발견할 수 있게 해줍니다. display 함수를 작성하다가 실수로 필드를 수정하는 경우, 컴파일러는 버그가 프로그램에 유입되도록 내버려 두는 대신 즉시 이를 차단합니다.

challenge icon

챌린지

쉬움

온도 값을 저장하고 읽기 전용 및 수정 작업을 모두 제공하는 Temperature 모듈을 만들어 보겠습니다. 이를 통해 const 포인터를 사용하여 데이터를 읽기만 하는 함수와 데이터를 변경하는 함수를 명확하게 구분하는 연습을 할 수 있습니다.

세 개의 파일을 생성하게 됩니다:

  • temperature.h: 단일 double celsius 멤버를 가진 Temperature 구조체를 선언합니다. 또한 다음 세 가지 함수를 선언합니다:
    • temp_display — Temperature에 대한 const 포인터를 받아 현재 온도를 출력합니다 (읽기 전용)
    • temp_adjust — Temperature에 대한 일반 포인터와 double 타입의 amount를 받아 celsius에 해당 양을 더합니다 (수정)
    • temp_to_fahrenheit — Temperature에 대한 const 포인터를 받아 화씨로 변환된 값을 반환합니다 (읽기 전용)
    TEMPERATURE_H 심볼을 사용하여 include guard를 적용하세요.
  • temperature.c: 세 가지 함수를 모두 구현합니다. temp_display 함수는 Current: {celsius}C 형식으로 출력해야 합니다. temp_to_fahrenheit 함수는 celsius * 9.0 / 5.0 + 32.0을 반환해야 합니다. const 포인터를 사용하는 함수는 구조체의 데이터를 수정할 수 없음을 기억하세요.
  • main.c: Temperature를 생성하고, 작업을 수행하며, 결과를 표시합니다.

두 개의 입력을 받게 됩니다: 초기 섭씨 온도 값 (double)과 조정할 양 (double).

메인 파일에서 다음을 수행하세요:

  1. 초기 섭씨 온도 값으로 Temperature를 초기화합니다.
  2. temp_display를 호출하여 시작 온도를 보여줍니다.
  3. temp_adjust를 호출하여 조정할 양만큼 온도를 수정합니다.
  4. temp_display를 다시 호출하여 업데이트된 온도를 보여줍니다.
  5. temp_to_fahrenheit를 사용하여 화씨 변환 값을 출력합니다.

결과를 다음 형식으로 출력하세요:

Current: {celsius}C
Current: {celsius}C
Fahrenheit: {fahrenheit}F

모든 온도 값에 %.1f를 사용하여 소수점 첫째 자리까지 표시하세요.

예를 들어, 초기 값이 20.0이고 조정 값이 5.0인 경우 출력은 다음과 같습니다:

Current: 20.0C
Current: 25.0C
Fahrenheit: 77.0F

치트 시트

const 키워드는 포인터 매개변수와 함께 사용되어 함수가 가리키는 데이터를 수정하지 않음을 나타낼 수 있습니다. 이를 const correctness(상수성 보장)라고 합니다.

포인터 매개변수가 const로 표시되면, 컴파일러는 해당 포인터를 통한 데이터 수정을 방지합니다:

typedef struct {
    int x;
    int y;
} Point;

// 읽기 전용 함수 - 포인트를 수정할 수 없음
void point_print(const Point *self) {
    printf("(%d, %d)\n", self->x, self->y);
    // self->x = 10;  // 오류: const 포인터를 통해 수정할 수 없음
}

// 수정 함수 - 포인트를 변경할 수 있음
void point_move(Point *self, int dx, int dy) {
    self->x += dx;
    self->y += dy;
}

const Point *self를 사용하면 컴파일러와 다른 프로그래머 모두에게 해당 함수가 읽기 전용 작업임을 알릴 수 있습니다. 이는 버그를 조기에 발견하는 데 도움이 됩니다. 아무것도 변경하지 않아야 하는 함수에서 실수로 데이터를 수정하려고 하면 컴파일러가 즉시 오류를 발생시킵니다.

모범 사례: 함수가 데이터를 수정할 필요가 없을 때마다 포인터 매개변수에 const를 사용하세요. 이렇게 하면 코드의 의도가 더 명확해지고 실수로 인한 수정을 방지할 수 있습니다.

직접 해보기

#include <stdio.h>
#include "temperature.h"

int main() {
    double initial_celsius, adjustment;
    scanf("%lf", &initial_celsius);
    scanf("%lf", &adjustment);
    
    // TODO: Temperature 구조체를 생성하고 initial_celsius로 초기화하세요
    
    // TODO: temp_display를 호출하여 시작 온도를 표시하세요
    
    // TODO: temp_adjust를 호출하여 조정 금액만큼 온도를 수정하세요
    
    // TODO: temp_display를 다시 호출하여 업데이트된 온도를 표시하세요
    
    // TODO: temp_to_fahrenheit를 사용하여 화씨 변환 값을 출력하세요
    // 형식: "Fahrenheit: %.1fF\n"
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Object Oriented Programming의 모든 레슨