• Tidak ada hasil yang ditemukan

8장. 포인터

N/A
N/A
Protected

Academic year: 2023

Membagikan "8장. 포인터"

Copied!
24
0
0

Teks penuh

(1)

8. 포인터

1

#include <stdio.h>

int main(void) {

int num;

printf(“Please enter an integer: ");

scanf("%d", &num);

if ( num < 0 )

printf("Is negative.\n");

printf("num = %d\n", num);

return 0;

}

■ 포인터란 무엇인지 알아보고, 포인터를 선언하고 사용하는 방법을 알아본다.

■ 포인터란 무엇인지 알아보고, 포인터를 선언하고 사용하는 방법을 알아본다.

■ 포인터를 사용할 때 주의사항을 알아본다.

■ 포인터를 사용할 때 주의사항을 알아본다.

학습목표

(2)

8장. 포인터

목차

3 포인터의 기본

•포인터란

•포인터 사용 시 주의사항

포인터의 기본

•포인터란

•포인터 사용 시 주의사항

배열과 포인터의 관계

•포인터의 연산

•포인터로서의 배열

•배열의 원소를 가리키는 포인터

•배열과 포인터의 차이점

배열과 포인터의 관계

•포인터의 연산

•포인터로서의 배열

•배열의 원소를 가리키는 포인터

•배열과 포인터의 차이점

포인터와 문자열

•문자열 상수

•문자열 포인터

•const 포인터

포인터와 문자열

•문자열 상수

•문자열 포인터

•const 포인터

포인터의 개념(1/2)

주소(address)를 저장하는 변수

포인터 변수의 크기(주소의 크기)는 시스템에 따라 다르다.

ƒ포인터

포인터의 기본

(3)

포인터의 개념(2/2)

포인터 변수는 다른 변수를 가리키는 변수이다.

포인터는 주소를 이용해서 특정 변수에 접근할 수 있도록 도와준다.

8장. 포인터

ƒ포인터

포인터의 기본

5

포인터의 선언(1/2)

char*는 char형 변수의 주소, int*는 int형 변수의 주소, double*는 double형 변수 의 주소를 저장한다.

char*형 변수는 char형 변수를 가리키고, int*형 변수는 int형 변수를 가리키고, double*형 변수는 double형 변수를 가리킨다.

ƒ포인터

포인터의 기본

(4)

포인터의 선언(2/2)

포인터 변수의 크기는 포인터 변수가 가리키는 변수의 데이터형에 관계없이 항상 같다.

8장. 포인터

ƒ포인터

포인터의 기본

7

포인터 변수와 포인터형의 크기

ƒ포인터

포인터의 기본

01: /* Ex08_01.c */

02: #include <stdio.h>

03:04: int main(void) 05: {

06: char *pc;

07: int *pi;

08: double *pd;

09:10: printf("pc의 크기 : %d\n", sizeof(pc));

11: printf("pi의 크기 : %d\n", sizeof(pi));

12: printf("pd의 크기 : %d\n", sizeof(pd));

13:14: printf("char* 의 크기 : %d\n", sizeof(char*));

15: printf("short* 의 크기 : %d\n", sizeof(short*));

16: printf("int* 의 크기 : %d\n", sizeof(int*));

17: printf("float* 의 크기 : %d\n",sizeof(float*));

18: printf("double*의 크기 : %d\n", sizeof(double*));

19:20: return 0;

21: }

포인터 변수의 선언

포인터 변수 크기 구하기

포인터 형의 크기 구하기

(5)

포인터의 사용(1/3)

포인터를 사용하려면 주소 구하기 연산자(address-of operator)간접 참조 연 산자(indirection operator)가 필요하다.

8장. 포인터

ƒ포인터

포인터의 기본

9

포인터의 사용(2/3)

주소 구하기 연산자 : & 다음에 나오는 변수의 주소를 구하는 데 사용

ƒ포인터

포인터의 기본

(6)

포인터의 사용(3/3)

간접 참조 연산자 : 포인터 변수가 가리키는 변수에 접근해서 값을 읽어오거나 변 경하는 데 사용

* 연산자는 반드시 포인터 변수 앞에만 사용할 수 있다.

8장. 포인터

ƒ포인터

포인터의 기본

11

포인터 변수의 선언 및 사용 예

ƒ포인터

포인터의 기본

01: /* Ex08_02.c */

02: #include <stdio.h>

03:04: int main(void) 05: {

06: int x;

07: int *p;

08:09: p = &x;

10: *p = 10;

11:12: printf("*p = %d\n", *p);

13: printf("x = %d\n", x);

14:15: printf("p = %p\n", p);

16: printf("&x = %p\n", &x);

17:18: printf("&p = %p\n", &p);

19:20: return 0;

21: }

int형 변수의 선언 int*형 변수의 선언

px의 주소 저장 p가 가리키는 변수에 접근

(7)

이중 포인터

포인터 변수의 주소를 저장하는 포인터 변수

이중 포인터가 가리키는 포인터를 이용해서 변수에 접근하려면 **처럼 두 번 간 접 참조를 해야 한다.

8장. 포인터

ƒ포인터

포인터의 기본

13

포인터형과 변수의 데이터형

포인터 변수의 데이터형이 반드시 포인터 변수가 가리키는 변수의 데이터형과 일 치해야 한다.

ƒ포인터 사용시 주의 사항

포인터의 기본

(8)

잘못된 포인터(1/2)

포인터도 변수이므로 반드시 초기화해야 한다.

포인터 변수를 초기화하지 않고 사용하면 실행 에러가 발생한다.

널 포인터 : 포인터가 다른 변수를 가리키지 않을 때는 NULL(0)로 초기화한다.

8장. 포인터

ƒ포인터 사용시 주의 사항

포인터의 기본

15

잘못된 포인터(2/2)

포인터를 안전하게 사용하려면 우선 포인터가 널 포인터인지를 검사한다.

ƒ포인터 사용시 주의 사항

포인터의 기본

(9)

포인터와 +, - 연산(1/2)

p+N은 p가 가리키는 데이터형 N개 크기만큼 증가된 주소가 연산의 결과이다.

p-N은 p가 가리키는 데이터형 N개 크기만큼 감소된 주소가 연산의 결과이다.

8장. 포인터

ƒ포인터의 연산

배열과 포인터의 관계

17

포인터와 +, - 연산(2/2)

‘포인터-포인터’ 연산은 두 포인터의 차를 구하는 데 사용된다.

ƒ포인터의 연산

배열과 포인터의 관계

(10)

포인터의 더하기, 빼기 예(1/2)

8장. 포인터

ƒ포인터의 연산

배열과 포인터의 관계

19 01: /* Ex08_03.c */

02: #include <stdio.h>

03:04: int main(void) 05: {

06: char ch;

07: char *pc = &ch;

08:09: int n;

10: int *pi = &n;

11:12: double d;

13: double *pd = &d;

14:15: int arr[3];

16: int i;

17:18: for(i = 0 ; i < 3 ; i++)

19: printf("pc+%d = %p\n", i, pc+i);

20:

char*형 변수의 선언

int*형 변수의 선언

double*형 변수의 선언

char*형에 정수를 더하는 연산

포인터의 더하기, 빼기 예(2/2)

ƒ포인터의 연산

배열과 포인터의 관계

21: for(i = 0 ; i < 3 ; i++)

22: printf("pi+%d = %p\n", i, pi+i);

23:24: for(i = 0 ; i < 3 ; i++)

25: printf("pd+%d = %p\n", i, pd+i);

26:27: for(i = 0 ; i < 5 ; i++)

28: printf("&arr[%d]-&arr[0] = %d\n", i, &arr[i]-&arr[0]);

29:30: return 0;

31: }

double*형에 정수를 더하는 연산

포인터의 차를 구하는 연산 int*형에 정수를 더하는 연산

(11)

포인터와 ++, -- 연산(1/2)

포인터에 대한 증감 연산(++, --)도 포인터형에 의해 연산의 결과가 결정된다.

8장. 포인터

ƒ포인터의 연산

배열과 포인터의 관계

21

포인터의 증가 연산자 이용 예

ƒ포인터의 연산

배열과 포인터의 관계

01: /* Ex08_04.c */

02: #include <stdio.h>

03:04: int main(void) 05: {

06: int arr[5] = {10, 20, 30, 40, 50};

07: int *p = &arr[0];

(12)

포인터로서의 배열(1/2)

인덱스 없이 배열명만 사용하면 배열의 시작 주소를 의미하는 주소 상수이다.

배열의 시작 주소를 구할 때는 & 없이 배열명만 사용한다.

배열명은 주소 상수인 것처럼 사용할 수 있다.

인덱스를 사용하는 대신 배열의 시작 주소로 포인터 연산을 하면 배열의 특정 원소에 접근할 수 있다.

8장. 포인터

ƒ포인터로서의 배열

배열과 포인터의 관계

23

포인터로서의 배열(2/2)

*(arr+i)arr[i]를 의미한다.

배열의 시작 주소에서 int i개 크기만큼 증가된 주소에 있는 값

ƒ포인터로서의 배열

배열과 포인터의 관계

(13)

포인터로서의 배열의 사용 예(1/2)

8장. 포인터

ƒ포인터로서의 배열

배열과 포인터의 관계

25 01: /* Ex08_05.c */

02: #include <stdio.h>

03:04: int main(void) 05: {

06: int arr[5] = {10, 20, 30, 40, 50};

07: int i;

08:09: for(i = 0 ; i < 5 ; i++)

10: {

11: printf("&arr[%d] = %p, ", i, &arr[i]);

12: printf("arr+%d = %p\n", i, arr+i);

13: }

14:15: for(i = 0 ; i < 5 ; i++)

16: {

17: printf("arr[%d] = %d, ", i, arr[i]);

18: printf("*(arr+%d) = %d\n", i, *(arr+i));

19: }

포인터의 차를 구하는 연산 int배열의 선언 및 초기화

배열 원소의 주소 구하기

배열 원소의 값 구하기

포인터로서의 배열의 사용 예(2/2)

ƒ포인터로서의 배열

배열과 포인터의 관계

20:21: return 0;

22: }

(14)

배열의 원소를 가리키는 포인터(1/2)

배열의 시작 주소로 초기화된 포인터를 이용해서 배열의 모든 원소에 접근할 수 있다.

포인터 변수를 배열 이름인 것처럼 사용할 수 있다.

8장. 포인터

ƒ배열의 원소를 가리키는 포인터

배열과 포인터의 관계

27

배열의 원소를 가리키는 포인터(2/2)

배열의 원소를 가리키는 포인터는 배열의 어떤 원소든지 가리킬 수 있다.

포인터가 배열의 원소가 아닌 일반 변수를 가리킬 때도 *(p+i) == p[i]는 항상 성 립한다.

ƒ배열의 원소를 가리키는 포인터

배열과 포인터의 관계

(15)

포인터를 배열처럼 사용하는 경우(1/2)

8장. 포인터

ƒ포인터로서의 배열

배열과 포인터의 관계

29 01: /* Ex08_06.c */

02: #include <stdio.h>

03:04: int main(void) 05: {

06: int arr[5] = {10, 20, 30, 40, 50};

07: int * p = arr;

08: int i;

09:10: for(i = 0 ; i < 5 ; i++)

11: {

12: printf("arr+%d = %p, ", i, arr+i);

13: printf("p+%d = %p\n", i, p+i);

14: }

15:

배열의 시작 주소로 초기화된 포인터

배열 원소의 주소 구하기

포인터를 배열처럼 사용하는 경우(2/2)

ƒ포인터로서의 배열

배열과 포인터의 관계

16: for(i = 0 ; i < 5 ; i++)

17: {

18: printf("arr[%d] = %d, ", i, arr[i]);

19: printf("p[%d] = %d\n", i, p[i]);

20: }

21:22: return 0;

배열 원소의 값 구하기

(16)

배열과 포인터의 차이점

배열이 메모리에 할당되고 나면, 배열의 시작 주소를 변경할 수 없다.

포인터 변수는 값을 변경할 수 있으므로, 포인터 변수에 보관된 주소는 변경할 수 있다.

8장. 포인터

ƒ배열과 포인터의 차이점

배열과 포인터의 관계

31

문자열 상수(1/3)

문자열 상수는 문자열의 첫 문자가 놓여진 곳의 주소값을 갖는 상수로 취급된다.

문자열 리터럴은 다른 리터럴과는 달리 메모리에 보관해두고 사용한다.

ƒ문자열 상수

포인터와 문자열

(17)

문자열 상수(2/3)

문자열 리터럴은 메모리에 보관하지만 변수처럼 값을 변경할 수는 없다.

값을 읽어볼 수만 있고 변경할 수 없는 특별한 메모리 영역에 할당 문자열 리터럴의 내용을 변경하려고 하면 실행 에러 발생

8장. 포인터

ƒ문자열 상수

포인터와 문자열

33

문자열 상수(3/3)

char*형 변수 p가 문자열 리터럴을 가리킬 때, 문자열 리터럴의 내용은 변경할 수 없지만, char*형 변수에 다른 문자열 리터럴의 주소를 대입할 수는 있다.

ƒ문자열 상수

포인터와 문자열

(18)

문자열 리터럴의 의미

8장. 포인터

ƒ문자열 상수

포인터와 문자열

35 01: /* Ex08_07.c */

02: #include <stdio.h>

03: #include <string.h>

04:05: int main(void) 06: {

07: char *p = "abcde";

08:09: printf("p = %s\n", p);

10: printf("p = %p\n", p);

11: printf("p = %p\n", "abcde");

12:13: p[0] = 'A';

14: strcpy(p, "hello");

15:16: return 0;

17: }

문자열 리터럴의 주소로 초기화된 포인터

실행 에러 발생

실행 에러 발생!

문자열의 대입

문자 배열에는 문자열을 직접 대입할 수 없다.

문자열의 내용을 변경하려면 = 연산자 대신 strcpy 함수를 이용해야 한다.

ƒ문자열 상수

포인터와 문자열

(19)

문자열의 비교

문자열의 내용을 비교할 때 == 연산자를 사용하면 안 된다.

문자열의 내용을 비교하려면 == 연산자 대신 strcmp 함수를 이용해야 한다.

8장. 포인터

ƒ문자열 상수

포인터와 문자열

37

문자열 포인터(1/2)

char*형 변수에는 문자열 리터럴의 주소를 저장할 수도 있고, 문자 배열의 주소를 저장할 수도 있다.

char*형 변수가 문자열 리터럴를 가리키는지 문자 배열을 가리키는지에 따라, 실 행 에러가 발생할 수도 있다.

ƒ문자열 포인터

포인터와 문자열

(20)

문자열 포인터(2/2)

변경 가능한 문자열을 가리킬 때는 char*형을 사용한다.

변경할 수 없는 문자열을 가리킬 때는 const char*형을 사용한다.

8장. 포인터

ƒ문자열 포인터

포인터와 문자열

39

const 포인터

포인터 변수를 선언할 때도 const 키워드를 사용할 수 있다.

const가 사용되는 위치에 따라 포인터 변수의 의미가 달라진다.

ƒconst 포인터

포인터와 문자열

(21)

const 키워드가 데이터형 앞에 있는 경우

포인터가 가리키는 변수의 값을 읽어볼 수만 있고 변경할 수 없다.

포인터 변수 자신의 값(주소)은 변경할 수 있다.

8장. 포인터

ƒconst 포인터

포인터와 문자열

41

const 키워드가 포인터 변수명 앞에 있는 경우

포인터 변수 자신의 값(주소)을 변경할 수 없다.

포인터가 가리키는 변수의 값은 변경할 수 있다.

ƒconst 포인터

포인터와 문자열

(22)

const 키워드가 양쪽 모두에 있는 경우

포인터가 가리키는 변수의 값도 변경할 수 없고 포인터 변수 자신의 값(주소)도 변경할 수 없다.

8장. 포인터

ƒconst 포인터

포인터와 문자열

43

포인터의 기본

포인터 : 다른 변수의 주소를 저장하는 변수 포인터의 선언 : 데이터 형, *, 변수명이 필요하다.

int * p;

포인터의 사용 : 변수의 주소를 구할 때는 주소 구하기 연산자 &를 이용하고, 포 인터가 가리키는 변수에 접근할 때는 간접 참조 연산자 *를 이용한다.

int *p = &x;

*p = 10;

포인터 사용 시 주의사항 : 포인터 변수는 포인터가 가리키는 변수의 데이터 형과 일치하도록 선언해야 한다. 잘못된 포인터를 사용하는 것은 위험하므로, 포인터가 가리키는 변수가 없을 때는 NULL을 저장한다.

학습정리

(23)

포인터와 배열의 관계

포인터로서의 배열 : 배열의 이름은 배열의 시작 주소이므로 포인터처럼 사용할 수 있다.

arr[i]는 *(arr + i)와 같다.

배열의 원소를 가리키는 포인터 : 배열의 원소를 가리키는 포인터는 배열처럼 사 용할 수 있다.

*(p + i)는 p[i]와 같다.

배열과 포인터의 차이점 : 배열의 시작 주소는 변경할 수 없지만 포인터에 저장된 주소는 변경할 수 있다.

8장. 포인터

학습정리

45

포인터와 문자열

문자열 리터럴 : 문자열 리터럴의 주소를 의미

char *p = "abcde";

Æ

p에는 "abcde"의 주소 저장

문자열 포인터 : 문자열 포인터가 문자열 리터럴을 가리킬 때는 문자열의 내용을 변경할 수 없지만, 문자열 포인터가 문자 배열을 가리킬 때는 문자열의 내용을 변 경할 수 있다.

학습정리

(24)

8. 포인터

47 NEXTChapter

9. 구조체

수고하셨습니다.

질문 있습니까?

Referensi

Dokumen terkait

Dokumen ini telah ditandatangani secara elektronik menggunakan sertifikat elektronik yang diterbitkan oleh Balai Sertifikasi Elektronik

Label Halal No Pertanyaan Alternatif Jawaban STS TS KS S SS 1 Saya mengetahui label halal yang dikeluarkan MUI 2 Saya selalu mempertimbangkan ada tidaknya logo label