티스토리 뷰
반응형
C언어 기초 Chapter 14: 포인터와 함수 (배열 전달, Call by Value & Reference, const)
14-1. 함수의 인자로 배열 전달하기
배열 전달 기본
- 함수에 배열을 넘기면, 사실은 배열의 첫 번째 원소 주소가 전달됨
- 따라서 배열 크기 정보는 따로 넘겨줘야 함
#include <stdio.h>
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main(void) {
int nums[5] = {1, 2, 3, 4, 5};
printArray(nums, 5);
return 0;
}
👉 출력: 1 2 3 4 5
배열 원소 수정하기
#include <stdio.h>
void addOne(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] += 1;
}
}
int main(void) {
int nums[3] = {10, 20, 30};
addOne(nums, 3);
for (int i = 0; i < 3; i++) {
printf("%d ", nums[i]); // 11 21 31
}
return 0;
}
👉 함수 안에서 배열 값이 실제로 변경됨 (주소 전달 방식이기 때문)
14-2. Call by Value vs. Call by Reference
Call by Value (값에 의한 전달)
- 변수 값 자체를 복사해서 함수에 전달
- 원본 값은 변하지 않음
#include <stdio.h>
void changeValue(int x) {
x = 100; // 지역 변수 x만 변경
}
int main(void) {
int a = 10;
changeValue(a);
printf("a = %d\n", a); // 10
return 0;
}
Call by Reference (참조에 의한 전달)
- 변수의 주소를 전달
- 함수 안에서 원본 값을 직접 변경 가능
#include <stdio.h>
void changeValue(int *x) {
*x = 100; // 실제 변수 값 변경
}
int main(void) {
int a = 10;
changeValue(&a);
printf("a = %d\n", a); // 100
return 0;
}
👉 C언어는 기본적으로 Call by Value지만, 포인터를 이용하면 Call by Reference 효과를 낼 수 있음
14-3. 포인터 대상의 const 선언
const 포인터 종류
- 포인터가 가리키는 값 변경 불가
const int *p;
- p는 다른 곳을 가리킬 수 있음
- 하지만 *p 값은 변경 불가
int a = 10, b = 20;
const int *p = &a;
p = &b; // 가능
//*p = 30; // ❌ 불가능
- 포인터 자체 변경 불가
int * const p = &a;
- p가 다른 변수를 가리킬 수 없음
- 하지만 *p 값은 변경 가능
int a = 10, b = 20;
int * const p = &a;
*p = 30; // 가능
// p = &b; // ❌ 불가능
- 값도 변경 불가, 포인터도 변경 불가
const int * const p = &a;
핵심 정리 ✅
- 배열은 함수에 전달될 때 주소(포인터) 로 전달됨
- C는 기본적으로 Call by Value → 원본 불변
- 포인터를 사용하면 Call by Reference처럼 원본 수정 가능
- const 와 포인터 조합은 값 보호 / 포인터 보호 / 둘 다 보호 가능
연습 문제 ✍️
- 배열 {1,2,3,4,5} 를 함수로 전달해 모든 원소에 +10 한 뒤 결과 출력하세요.
- Call by Value와 Call by Reference 차이를 보여주는 예제를 작성하세요.
- const int *p, int * const p, const int * const p 의 차이를 실험해 보세요.
👉 연습문제 정답은? ▼
Chapter 14 연습문제 풀이
1) 배열 {1,2,3,4,5} 를 함수로 전달해 모든 원소에 +10 하기
#include <stdio.h>
void addTen(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] += 10;
}
}
int main(void) {
int nums[5] = {1, 2, 3, 4, 5};
addTen(nums, 5);
printf("배열 원소: ");
for (int i = 0; i < 5; i++) {
printf("%d ", nums[i]);
}
return 0;
}
👉 출력:
배열 원소: 11 12 13 14 15
2) Call by Value vs Call by Reference 차이
#include <stdio.h>
void changeByValue(int x) {
x = 100; // 지역 변수만 바뀜
}
void changeByReference(int *x) {
*x = 200; // 실제 값 바뀜
}
int main(void) {
int a = 10;
changeByValue(a);
printf("Call by Value 후 a = %d\n", a); // 10
changeByReference(&a);
printf("Call by Reference 후 a = %d\n", a); // 200
return 0;
}
👉 출력:
Call by Value 후 a = 10
Call by Reference 후 a = 200
3) const int *p, int * const p, const int * const p 차이 실험
#include <stdio.h>
int main(void) {
int a = 10, b = 20;
// 1) const int *p → 값 변경 불가, 포인터 이동 가능
const int *p1 = &a;
// *p1 = 30; // ❌ 불가능
p1 = &b; // ✅ 가능
// 2) int * const p → 포인터 이동 불가, 값 변경 가능
int * const p2 = &a;
*p2 = 40; // ✅ 가능
// p2 = &b; // ❌ 불가능
// 3) const int * const p → 값 변경 불가, 포인터 이동 불가
const int * const p3 = &a;
// *p3 = 50; // ❌ 불가능
// p3 = &b; // ❌ 불가능
printf("a = %d, b = %d\n", a, b);
return 0;
}
👉 실행 결과는 컴파일러에 따라 경고 또는 오류가 다를 수 있지만, 원칙은:
- const int *p → 값 보호
- int * const p → 포인터 보호
- const int * const p → 값과 포인터 모두 보호
핵심 정리 ✅
- 배열을 함수에 전달하면 원소 값 변경 가능 (주소 전달)
- C는 기본적으로 Call by Value, 포인터 이용 시 Call by Reference 구현 가능
- 포인터 + const 조합으로 안전한 코드 작성 가능
반응형
'[문법] C언어' 카테고리의 다른 글
11) C언어 다차원 배열과 포인터 완전정리: 2차원 배열부터 포인터까지 (2) | 2025.09.02 |
---|---|
10) C언어 포인터의 포인터: 이중 포인터 개념, 함수 활용, 동적 메모리 할당 (0) | 2025.09.02 |
8) C언어 포인터와 배열 완전정리: 관계, 연산, 문자열, 포인터 배열 (2) | 2025.09.01 |
7) C언어의 1차원 배열과 포인터에 대해 알아보자 (2) | 2025.09.01 |
6) C언어 함수 완전정리: 정의, 호출, 변수 범위와 재귀까지 (4) | 2025.08.31 |