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 함수를 작성하다가 실수로 필드를 수정하는 경우, 컴파일러는 버그가 프로그램에 유입되도록 내버려 두는 대신 즉시 이를 차단합니다.
챌린지
쉬움온도 값을 저장하고 읽기 전용 및 수정 작업을 모두 제공하는 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).
메인 파일에서 다음을 수행하세요:
- 초기 섭씨 온도 값으로
Temperature를 초기화합니다. temp_display를 호출하여 시작 온도를 보여줍니다.temp_adjust를 호출하여 조정할 양만큼 온도를 수정합니다.temp_display를 다시 호출하여 업데이트된 온도를 보여줍니다.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;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.