[12] 포인터를 입력으로 이용하는 함수 (function using pointers as inputs)

C언어 함수 정리

참고 문헌 (Ch 63): https://dojang.io/mod/page/view.php?id=549

포인터 매개변수 사용하기

일반적인 자료형을 이용했을 때의 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

void swapNumber(int first, int second) // 반환값 없음, int형 매개변수 두 개 지정
{
int temp; // 임시 보관 변수

temp = first;
first = second;
second = temp;
}

int main()
{
int num1 = 10;
int num2 = 20;

swapNumber(num1, num2); // 변수 num1과 num2를 넣어줌

printf("%d %d\n", num1, num2); // 10 20: swapNumber 함수와는 상관없이
// 처음 저장한 10과 20이 출력됨

return 0;
}

반환형이 void이기 때문에, 두 변수를 받아서 처리하더라도 아무런 변화가 나타나지 않는다.
매개변수를 포인터로 이용해야 해당 주소값에 있는 변수에 직접 접근해서 값을 바꿀 수 있다.

1
2
3
반환값자료형 함수이름(자료형 *매개변수1, 자료형 *매개변수2)
{
}

예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

void swapNumber(int *first, int *second) // 반환값 없음, int 포인터 매개변수 두 개 지정
{
int temp; // 임시 보관 변수

// 역참조로 값을 가져오고, 값을 저장함
temp = *first;
*first = *second;
*second = temp;
}

int main()
{
int num1 = 10;
int num2 = 20;

swapNumber(&num1, &num2); // &를 사용하여 num1과 num2의 메모리 주소를 넣어줌

printf("%d %d\n", num1, num2); // 20 10: swapNumber에 의해서 num1과 num2의 값이 서로 바뀜

return 0;
}

매개변수 포인터의 처리를 이해하기 쉽게 하는 방법

매개변수에서 처리할 포인터를 받아오는 경우, 입력과 출력에 대한 표시를 해주는 경우가 있다.

1
2
3
4
5
6
7
8
9
10
#define IN
#define OUT

// ↓ 일반적인 매개변수
void GetValue(IN int a, OUT int *b)
{ // ↑ 값이 바깥으로 나오는 매개변수
printf("%d\n", a);

*b = 10;
}

IN과 OUT 표시는 컴파일 할 때 아무런 영향을 주지 않는 매크로가 된다. 사람만 알아볼 수 있는 부분

void 포인터 매개변수 사용하기

void 포인터 매개변수를 이용하면, 자료형 변환을 하지 않아도 모든 자료형을 함수에 넣을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>

enum TYPE {
TYPE_CHAR,
TYPE_INT,
TYPE_FLOAT
};

void swapValue(void *ptr1, void *ptr2, enum TYPE t) // 반환값 없음, void 포인터 매개변수 두 개와
{ // 변수의 자료형을 알려줄 열거형을 받음
switch (t)
{
case TYPE_CHAR: // 문자면 char *로 변환한 뒤 역참조하여 값을 서로 바꿈
{
char temp;
temp = *(char *)ptr1;
*(char *)ptr1 = *(char *)ptr2;
*(char *)ptr2 = temp;
break;
}
case TYPE_INT: // 정수면 int *로 변환한 뒤 역참조하여 값을 서로 바꿈
{
int temp;
temp = *(int *)ptr1;
*(int *)ptr1 = *(int *)ptr2;
*(int *)ptr2 = temp;
break;
}
case TYPE_FLOAT: // 실수면 float *로 변환한 뒤 역참조하여 값을 서로 바꿈
{
float temp;
temp = *(float *)ptr1;
*(float *)ptr1 = *(float *)ptr2;
*(float *)ptr2 = temp;
break;
}
}
}

int main()
{
char c1 = 'a';
char c2 = 'b';
swapValue(&c1, &c2, TYPE_CHAR); // 변수의 메모리 주소와 TYPE_CHAR를 넣음
printf("%c %c\n", c1, c2); // b a: swapValue에 의해서 값이 서로 바뀜

int num1 = 10;
int num2 = 20;
swapValue(&num1, &num2, TYPE_INT); // 변수의 메모리 주소와 TYPE_INT를 넣음
printf("%d %d\n", num1, num2); // 20 10: swapValue에 의해서 값이 서로 바뀜

float num3 = 1.234567f;
float num4 = 7.654321f;
swapValue(&num3, &num4, TYPE_FLOAT); // 변수의 메모리 주소와 TYPE_FLOAT를 넣음
printf("%f %f\n", num3, num4); // 7.654321f 1.234567:
// swapValue에 의해서 값이 서로 바뀜

return 0;
}

이중 포인터 매개변수 사용하기

포인터 매개변수를 이용해서 정수, 실수 등의 값 대신 포인터(메모리 주소)를 얻어오기 위한 방법이 필요!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

void allocMemory(void *ptr, int size) // 반환값 없음, void 포인터 매개변수 지정
{
ptr = malloc(size); // ptr은 allocMemory를 벗어나면 사용할 수 없음
}

int main()
{
long long *numPtr = NULL;

// numPtr과 할당할 크기를 넣어줌
allocMemory(numPtr, sizeof(long long));

*numPtr = 10; // 메모리가 할당되지 않았으므로 실행 에러
printf("%lld\n", *numPtr);

free(numPtr);

return 0;
}

디버그 포인트로 찍어보니, 선언한 값에 내용물이 아무것도 들어있지 않다. 이를 해결하기 위해서 이중 포인터를 이용.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일

void allocMemory(void **ptr, int size) // 반환값 없음, void 이중 포인터 매개변수 지정
{
*ptr = malloc(size); // void **ptr을 역참조하여 void *ptr에 메모리 할당
}

int main()
{
long long *numPtr;

// 단일 포인터 long long *numPtr의 메모리 주소는 long long **와 같음, 할당할 크기도 넣음
allocMemory(&numPtr, sizeof(long long));

*numPtr = 10;
printf("%lld\n", *numPtr);

free(numPtr); // 동적 메모리 해제

return 0;
}

이렇게 하면 값이 되게 잘나온다. 이해가 잘 안되니까 보면서 좀 더 생각해보기


문자열 매개변수 사용하기

매개변수로 문자열을 받을 땐 매개변수를 문자열 포인터로 지정! 여러가지 형태로 문자열 입력을 지정할 수 있다.

char 포인터 매개변수 1개로 이용

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

void helloString(char *s1) // 반환값 없음, char 포인터 매개변수 한 개 지정
{
printf("Hello, %s\n", s1); // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
helloString("world!"); // Hello, world!: 함수를 호출할 때 문자열을 전달

return 0;
}

베열 형태의 문자열도 전달할 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

void helloString(char *s1) // 반환값 없음, char 포인터 매개변수 한 개 지정
{
printf("Hello, %s\n", s1); // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
char s1[10] = "world!"; // 배열 형태의 문자열

helloString(s1); // Hello, world!: 함수를 호출할 때 배열 전달

return 0;
}

매개변수 뒤에 []를 붙여서 설정, 이 때 크기는 생략!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

void helloString(char s1[]) // 반환값 없음, char 배열을 매개변수로 지정, 크기 생략
{
printf("Hello, %s\n", s1); // Hello, 와 매개변수를 조합하여 문자열 출력
}

int main()
{
char s1[10] = "world!"; // 배열 형태의 문자열

helloString(s1); // Hello, world!: 함수를 호출할 때 배열 전달
helloString("world!"); // Hello, world!: 함수를 호출할 때 문자열 전달

return 0;
}