질문 이력
C에서 return 연산자는 함수 작업을 명시적으로 종료하고 호출한 코드에 결과를 전달하기 위해 도입되었습니다. 초기 프로그래밍 언어에서는 항상 값을 반환하는 기능이 존재하지 않았으며, return 메커니즘은 계산 결과를 명시적으로 지정할 수 있게 해주었습니다. 이는 프로그램의 표현력과 안전성을 높였습니다.
문제
주요 작업: 함수를 올바르게 종료하고 필요한 경우 특정 형식에 해당하는 값을 반환하는 것입니다. 잘못된 형식의 값 반환이나 존재하지 않는 또는 지역 변수에 대한 포인터 반환, 또는 호출 측에서 반환된 값을 무시하는 경우에 오류가 자주 발생합니다.
해결책
코드 예:
#include <stdio.h> struct Point { int x, y; }; struct Point make_point(int x, int y) { // 구조체 반환(복사) struct Point p = {x, y}; return p; } int* dangerous() { int num = 42; return # // 위험: 지역 변수의 주소 반환! } void do_nothing() { return; // void 형식의 함수에 대해 올바름 } int main() { struct Point p = make_point(3, 4); printf("%d %d ", p.x, p.y); int* ptr = dangerous(); // UB: ptr는 해제된 메모리를 가리킴 }
주요 특징:
값이 없는(void) 함수에서 return을 사용할 수 있나요?
답변: 네, void 함수에서 "return;"을 쓸 수 있지만, 표현식을 지정하는 것은 불가능합니다(예: return x;는 void 함수에서 허용되지 않음).
함수에서 배열을 반환할 때 무슨 일이 발생하나요?
답변: C에서는 배열을 직접 반환할 수 없습니다. 포인터(예: 정적 배열)를 반환할 수 있지만, 일반적으로 포인터와 크기를 함께 반환하거나 동적으로 할당된 배열을 사용하는 것이 좋습니다.
int* make_arr() { static int arr[5] = {1,2,3,4,5}; return arr; // 정적 배열은 함수 종료 후에도 살아있음 }
왜 지역 변수의 포인터를 반환하는 것이 위험한가요?
답변: 함수 종료 후 지역 변수의 메모리는 해제됩니다(스택 영역). 반환된 포인터를 사용하는 것은 정의되지 않은 동작을 초래합니다.
부정적 사례
함수가 지역 변수에 대한 포인터를 반환하고 호출자가 "쓰레기"를 받아 예측할 수 없는 동작과 드문 플로팅 버그가 발생합니다.
장점:
단점:
긍정적 사례
반환된 구조체 사용(값으로 복사됨) 또는 정적/동적 메모리의 포인터 반환:
장점:
단점: