'Self' 포인터
Coddy C 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 7번째.
Python이나 Java와 같은 객체 지향 언어에서 object.method()를 호출할 때, 언어는 자동으로 객체 자신을 메서드에 전달합니다. C에서는 구조체에 대한 포인터를 첫 번째 인수로 전달하여 이를 수동으로 수행해야 합니다.
이 포인터는 관례적으로 self (Python에서 빌려온) 또는 this (C++에서 유래한)라고 명명됩니다. 이것은 함수가 구조체의 데이터에 접근하여 이를 읽거나 수정할 수 있게 해줍니다:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
self 포인터는 함수가 메서드처럼 동작하게 만드는 요소입니다. 즉, 어떤 플레이어를 수정해야 할지 알고 있습니다. 이것이 없다면 함수는 특정 구조체 인스턴스에 접근할 방법이 없습니다. 이 함수를 호출할 때, 구조체의 주소를 전달합니다:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health는 이제 75입니다
포인터를 사용하는 것(구조체를 직접 전달하는 대신)은 수정을 위해 필수적입니다. 구조체를 값으로 전달하면 함수는 복사본을 받게 되며, 함수가 반환될 때 모든 변경 사항이 손실됩니다. 포인터는 변경 사항이 원래의 구조체에 유지되도록 보장합니다.
챌린지
쉬움경과된 초를 추적하는 Timer 모듈을 만들어 보겠습니다. 구조체의 내부 상태를 수정하기 위해 메서드처럼 작동하는 함수에서 "self" 포인터 패턴을 사용하는 연습을 하게 됩니다.
세 개의 파일을 생성해야 합니다:
timer.h: 단일int seconds멤버를 가진Timer구조체를 선언합니다. 또한 두 개의 함수를 선언합니다:timer_tick(Timer에 대한 포인터를 받아 지정된 초를 더함) 및timer_reset(Timer에 대한 포인터를 받아 초를 0으로 재설정함).TIMER_H심볼을 사용하여 include guard를 사용하세요.timer.c: 두 함수를 구현합니다.timer_tick함수는Timer *self와int amount를 인자로 받아 타이머의 초에 해당 금액을 더해야 합니다.timer_reset함수는Timer *self를 인자로 받아 초를 0으로 설정해야 합니다.main.c: Timer를 생성하고, 연산을 수행한 후 결과를 표시합니다.
두 개의 정수 입력을 받게 됩니다: 타이머의 초기 초(initial seconds)와 tick을 통해 더할 양(amount to add)입니다.
main 파일에서 다음을 수행하세요:
- 초기 초 값으로
Timer를 초기화합니다. timer_tick을 호출하여 지정된 양을 더합니다.- 현재 초를 출력합니다.
timer_reset을 호출하여 타이머를 재설정합니다.- 초를 다시 출력합니다 (0이어야 합니다).
결과를 다음 형식으로 출력하세요:
After tick: {seconds}
After reset: {seconds}예를 들어, 초기 값이 30이고 15초를 더하는 경우 출력은 다음과 같습니다:
After tick: 45
After reset: 0치트 시트
C 언어에서 구조체를 다루는 함수는 포인터 매개변수를 통해 구조체 인스턴스에 명시적으로 접근해야 하며, 관례적으로 이 매개변수의 이름은 self 또는 this로 지정됩니다:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
self 포인터를 사용하면 함수가 구조체의 데이터에 접근하고 이를 수정할 수 있습니다. 이러한 함수를 호출할 때는 구조체의 주소를 전달하십시오:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health는 이제 75입니다
수정을 위해서는 포인터를 사용하는 것이 필수적입니다. 값에 의한 전달(passing by value)은 복사본을 생성하므로 함수가 반환될 때 변경 사항이 사라지게 됩니다. 포인터는 변경 사항이 원래 구조체에 유지되도록 보장합니다.
직접 해보기
#include <stdio.h>
#include "timer.h"
int main() {
int initial_seconds, amount_to_add;
scanf("%d", &initial_seconds);
scanf("%d", &amount_to_add);
// TODO: Timer를 생성하고 initial_seconds로 초기화하세요
// TODO: amount_to_add 초를 더하기 위해 timer_tick을 호출하세요
// TODO: 현재 초를 "After tick: {seconds}" 형식으로 출력하세요
// TODO: 타이머를 리셋하기 위해 timer_reset을 호출하세요
// TODO: 초를 "After reset: {seconds}" 형식으로 다시 출력하세요
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.