본문 바로가기

C언어

C언어_스터디_3_포인터 활용

출처 : https://swexpertacademy.com/main/learn/course/lectureVideoPlayer.do

 

 

 

1. 포인터와 함수 매개변수

 

(1) 함수의 매개 변수

 - 함수에 전달한 값이 있는 경우 인자를 전달

 - 함수 측에서는 매개변수를 통해 전달받음

 

(2) 함수 인수 전달방법

   1) call by value

    - 값에 의한 호출

    - 인자의 값이 매개변수로 복사

    - 함수호출 측의 인자 자체에는 영향 없음

    - 즉, 함수 내에서 매개변수가 변화해도 그 함수 내에서만 영향

   2) call by reference

    - 참조에 의한 호출

    - 호출된 함수 측에서 포인터 매개변수로 받아 호출한 함수 측의 주소를 참조하도록 구성

    - 인자 주소가 매개변수에 복사, 호출된 함수에서 주소를 이용하여 인수에 접근

    - 매개변수 변화가 인자에 영향

 

(3) 함수 인수 전달방법 예제

   1) call by value

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 swap(int a, int b);
 
int main(void)
{
    int a,b;
 
    a = 5;
    b = 10;
    swap(a,b);
    printf("main() : a = %d\tb= %d\n",a ,b);
    return 0;
}
 
void swap(int a, int b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
    printf("swap() : a = %d\tb = %d\n", a, b);
}
 
 
 - 인자로 main 함수의 지역 변수(a,b) 전달
- swap 함수 수행 후, main 함수에서 a,b 내용 확인 시 값이 처음 상태로 유지
- 결과 :
swap() : a = 10 b = 5
main() : a = 5 b = 10

   2) call by reference

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 swap(int *a, int *b);
 
int main(void)
{
    int a,b;
 
    a = 5;
    b = 10;
    swap(&a,&b); // 인자를 주소로 전달
    printf("main() : a = %d\tb= %d\n",a ,b);
    return 0;
}
 
void swap(int* a, int* b)
{
    int temp;
    temp = *a;
    *= *b;
    *= temp;
    printf("swap() : a = %d\tb = %d\n"*a, *b);
}
 
 
- 보통, 함수 처리 결과를 2개 이상 반환하는 경우의 프로그램일 때 사용
- 결과 :
swap() : a = 10 b = 5
main() : a = 10 b = 5

 

 

 

 

 

2. main 함수의 매개변수 전달

 

(1) 명령어의 실행

 - 명령어 창에서 직접 명령어를 입력해서 실행하는 경우, 명령어 뒤에 인자를 붙여 사용

 - ex) ftp ftp.kernel.org

 

(2) main 함수의 원형

1
int main(int argc, char *argv[])

 - 프로그램 실행 시 인자를 전달받기 위해 main 함수의 원형에 대한 이해가 필요

 - argc : 인자의 개수 전달 / *argv : 인자의 목록 전달 (char* 배열이나 2중 포인터로 받아야 함)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
#include<string.h>
 
int main(int argc, char* argv[])
{
    char* path = "/tmp";
    char filename[1024];
 
    if(argc!=2){
        printf("Usage : %s filename\n", argv[0]);
        return 0;
    }
    strcpy(filename, path);
    strcat(filename, argv[1]);
    printf("filename : %s\n", filename);
    
    return 0;
}
 
 
- 흠.. 대충 개념만 알자

 

 

 

 

 

 

3. 함수 포인터

 

(1) 함수 포인터란?

 - 포인터는 함수 시작 번지를 넣어 사용 가능

 - 함수의 시작 주소를 포인터 변수에 대입

 

(2) 함수 포인터의 목적

 - 다양한 함수들이 서로 다른 환경에서 호출되는 경우 사용 (ex. 컴파일러, 어셈블러, 인터프리터 등의 소프트웨어 작성 시)

 - 동적으로 함수를 불러다 사용하고 필요없는 경우 삭제하는 동적 라이브러리 함수를 이용하는 경우

 

(3) 함수 포인터 선언

리턴타입 (*함수포인터변수명)(매개변수목록);
int(*fun)(int num); // int(*fun)(int); 도 가능. 즉, 매개변수 명은 생략 
- fun 변수에 시작 주소를 대입
- int 값을 반환하고 매개변수로 int 형의 num 하나만 선언
- int *fun() ---> int형 포인터(주소)를 반환하는 fun 함수 호출로 해석

 

(4) 함수의 시작 주소 확인

 - "배열 이름 = 배열 시작 주소"와 마찬가지로 함수 이름은 함수의 시작 번지를 통해 알 수 있음

 

(5) 함수 포인터 예제

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
#include <stdio.h>
 
int add(int x, int y);
 
int main(void)
{
    int (*calc)(int x, int y); // 함수 포인터 선언
    int x,y,z;
 
    x = 10;
    y = 20;
 
    calc=add; // add함수의 시작 주소를 대입
 
    z = calc(x,y); // 함수 포인터를 이용한 함수 간접 호출
 
    printf("add = %d\n", z);
    
    return 0;
}
 
int add(int x, int y)
{
    return x+y;
}
 

 

(6) 함수 포인터 배열

 - 배열 원소 각각이 함수 포인터 변수

 - 원형이 동일한 함수의 주소들이 모여있는 구조

 

   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
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
#include <stdio.h>
 
int add(int a, int b);
int subtract(int a, int b);
int multiply(int a, int b);
int divide(int a, int b);
 
int main(void)
{
    int (*fptr[4])(int a, int b);
    int a, b, result, op;
 
    fptr[0= add;
    fptr[1= subtract;
    fptr[2= multiply;
    fptr[3= divide;
 
    do{
        printf("두 개의 수를 입력\n");
        scanf("%d %d",&a,&b);
        printf("1. 더하기 2. 빼기 3. 곱하기 4. 나누기 5. 종료\n");
        printf("선택하십시오[0-5]\n");
        scanf("%d,&op");
 
        if(op == 5)
            break;
 
        result = (*fptr[op-1])(a,b);
    }while(1);
 
    return 0;
}
 
int add(int a, int b)
{
    return a+b;
}
 
int subtract(int a, int b)
{
    return a-b;
}
 
int multiply(int a, int b)
{
    return a*b;
}
 
int divide(int a, int b)
{
    return a/b;
}
 

 

 

 

 

 

4. void 포인터

 

(1) void형이란?

 - 값이 없을 때 이용하는 자료형

 - 반환 값이 없는 함수의 리턴 타입

 

(2) void*형

 - 주소를 저장하는 자료형

 - 어떤 유형의 주소도 저장 가능

 - void형은 크기가 없어 void* 변수가 가리키는 메모리를 얼마나 참조해야 하는지 확인 불가

(포인터가 가리키는 내용 참조 시 원래 자료형으로 형변환)

 - ex) printf("num = %d\n", *(int*)p); --> (int*)의 형변환을 해줌

 - 즉, void 포인터는 아직 값이 들어갈 때 자료형이 어떤 것인지 알 수 없을 경우 사용. 그렇기 때문에 함수 내에서 형변환을 이용하여 자료형에 따른 연산을 각각 설정

 

(3) 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
#include <stdio.h>
#include <string.h>
 
void swap(char* type, void* a, void* b)
 
int main(void)
{
    int a,b;
 
    a = 5;
    b = 10;
    swap("int"&a, &b);
    printf("main() : a = %d\t b= %d\n", a, b);
 
    c = 'a';
    d = 'b';
    swap("char"&c, &d);
    printf("main() : c = %c\td = %c\n", c, d);
}
 
void swap(char*type, void*a, void*b)
{
    int temp;
 
    if(!strcmp(type,"int")){
        temp = *(int*)a;
        *(int*)a = *(int*)b;
        *(int*)b = temp;
    } else if(!strcmp(type,"char")){
        temp = *(char*)a;
        *(char*)a = *(char*)b;
        *(char*)b = temp;
    }
}
 

 

 

 

 

 

5. 라이브러리 함수

 

(1) 라이브러리란?

 - C프로그램을 쉽게 개발하기 위해 미리 만들어놓은 함수들의 모음

 - 개발환경 구축 할 때, C컴파일러와 라이브러리가 설치되어 바로 사용 가능

 

(2) 표준입출력 함수의 이해

#include <stdio.h>

 - 우리가 항상 사용하던 stdio도 라이브러리의 일종

 

(3) 표준입출력 함수 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main(void)
{
    char buffer[80];
    char string[1024];
 
    printf("문자열을 입력하시오.\n");
    gets(buffer); // 라이브러리 사용, 입력
    sprintf(string,"입력된 문자열은 %s 입니다",buffer); // 라이브러리 사용, 추가
    puts(string); // 라이브러리 사용, 출력
    
    return 0;
}
 

 

(4) 문자 처리 함수

 - 문자의 특성 구분이 필요한 경우 사용하는 라이브러리는 아래와 같다.

#include <ctype.h>
int isalnum(int ch)   인자가 영문자나 숫자인 경우 참(0이 아닌 값) 반환, 그렇지 않은 경우 거짓(0) 반환
int isalpha(int ch)   ch로 전달된 인자가 영문자인 경우 참 반환, 그 외엔 거짓 반환
int isdigit(int ch)   ch에 전달된 인자가 숫자(0~9)인 경우 참 반환, 그 외에 거짓 반환
int iscntrl(int ch)   ch에 전달된 인자가 0~0x1f 사이에 있거나 0x7f(DEL)와 같은 제어문자인 경우 참 반환, 그 외에 거짓 반환
int isspace(int ch)   ch에 전달된 인자가 공백문자이면 참 반환, 그 외에는 거짓 반환
int ispunct(int ch)

  인자 ch가 공백문자를 제외한 구두점 문자인 경우 참 반환, 그 외에는 거짓 반환

  구두점 문자 : 영문자, 숫자, 공백문자를 제외한 출력 가능한 문자, 즉 특수문자

int tolwer(int ch), int toupper(int ch)

  함수 tolower는 ch가 영문자인 경우 소문자로 반환, 그 외에는 그대로 반환

  toupper는 대문자 반환

 

(5) 문자열 처리 함수

 - C에는 문자열 자료형이 제공되지 않음

#include <string.h>