Presentation is loading. Please wait.

Presentation is loading. Please wait.

11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.

Similar presentations


Presentation on theme: "11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const."— Presentation transcript:

1 11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const

2 포인터의 개념 포인터 변수는 다른 변수를 가리키는 변수다. 포인터 변수에는 다른 변수의 주소 값을 저장할 수 있다.
예를 들어서 포인터 변수 A가 다른 변수 B의 주소 값을 보관하고 있다면, 포인터 변수 A가 변수 B를 가리키고 있다고 말한다.

3 변수의 주소 변수의 주소란 변수가 포함하고 있는 제일 첫번째 바이트의 주소를 말한다.
예를 들어서 int 타입의 변수 a가 있다고 하면, 변수 a는 4바이트의 메모리 공간을 소유하게 된다. 메모리의 각 바이트 마다 주소가 있다. 그 중에서 첫번째 바이트의 주소를 변수 a의 주소라고 말한다.

4 포인터 변수에 변수의 주소를 보관하기 포인터 변수 p가 변수 a를 가리키도록 만드는 예 실행 결과
// 일반적인 변수를 정의한다. int a = 123; // 포인터 변수를 정의한다. int* p; // p가 a를 가리키도록 만든다. p = &a; // 관련 정보를 출력한다. cout << "&a = " << &a << "\n"; cout << "p = " << p << "\n"; cout << "&p = " << &p << "\n";

5 포인터 변수의 정의 포인터 변수를 정의할 때는 가리키고자 하는 변수의 타입을 지정해 두어야 한다. 다양한 타입의 포인터 변수
char c = 'C'; char* pc = &c; float f = 700.5f; float* pf = &f; bool b = true; bool* pb = &b; short int s = 456; short int* ps = &s;

6 가리킬 타입을 지정해야 하는 이유 메모리에는 타입에 대한 정보가 보관되지 않는다.
그러므로, 포인터 변수의 타입을 통해서 데이타의 크기나 종류를 알아낸다.

7 void 포인터 void* 타입의 포인터 변수는 어떤 타입의 변수라도 가리킬 수 있다.
void* p;

8 주소를 사용해서 정보에 접근하기 포인터 변수가 가리키는 변수에 접근하는 예 실행 결과 // p가 a를 가리키도록 만든다.
int a = 123; int* p = &a; // p가 가리키는 변수의 값을 얻는다. cout << "*p = " << *p << "\n"; // p가 가리키는 변수의 값을 변경한다. *p = 789; // 관련 정보를 출력한다. cout << "a = " << a << "\n";

9 포인터 안전하게 사용하기 잘못된 주소를 가진 포인터를 사용하는 것은 매우 위험하기 때문에, 포인터를 사용할 때는 다음의 가이드 라인을 따른다. 포인터 변수는 항상 0 혹은 NULL 값으로 초기화 한다. 포인터 변수를 사용하기 전에는 0 혹은 NULL 값을 가지고 있는지 확인한다. // 포인터 변수를 정의하고 초기화한다. int* p = NULL; // 이 상태에서 포인터를 사용해보자. if (NULL != p) *p = 30; // p가 변수를 가리키게 만들자 int a = 100; p = &a; if (!p)

10 Const 속성을 가진 변수 변수의 값이 변경되는 것을 막기위해서 Const 속성을 사용해서 변수를 정의할 수 있다.
const int a = 123; // a의 값을 바꾸려고 했으므로 컴파일 에러 발생!! a = 456; // 배열의 크기를 const 변수에 보관한다. const unsigned int arraySize = 100; // 배열을 정의한다. char characters[ arraySize ] = {0}; // 배열을 사용한다. for (int i = 0; i < arraySize; ++i) characters[i] = i + 1;

11 Const 와 포인터 (1) 포인터 변수에 Const 속성을 부여할 때는 다음의 두 변수를 고려할 수 있다. 포인터 변수 자체
포인터 변수가 가리키는 변수

12 Const 와 포인터 (2) 포인터 변수에 Const 속성을 적용한 3가지 경우를 비교해보자.
int i1 = 10; int i2 = 20; const int* p = &i1; p = &i2; // OK *p = 30; // FAIL int i1 = 10; int i2 = 20; int* const p = &i1; p = &i2; // FAIL *p = 30; // OK int i1 = 10; int i2 = 20; const int* const p = &i1; p = &i2; // FAIL *p = 30; // FAIL

13 01_ 포인터의 기본 02_ 포인터와 Const 03_ 포인터와 구조체
12장. 배열과 구조체와 포인터 01_ 포인터의 기본 02_ 포인터와 Const 03_ 포인터와 구조체

14 배열의 원소를 가리키는 포인터 포인터 변수를 사용해서 배열의 원소를 가리키는 예 int arrays[10];
int* p = &arryays[5]; [그림 12-1]

15 포인터 변수에 정수를 더하기 i 번째 원소를 가리키는 포인터 변수에 정수 n을 더하면 포인터 변수는 i + n 번째 원소를 가리키게 된다. 실행 결과 int array[10]; // 포인터가 array[5]를 가리키도록 만든다. int* p = &array[5]; cout << "p = " << p << "\n"; cout << "&array[5] = " << &array[5] << "\n"; // 포인터가 array[6]을 가리키도록 만든다. p++; cout << "&array[6] = " << &array[6] << "\n"; [그림 12-3] [그림 12-2]

16 포인터 변수간의 뺄셈 i 번째 원소를 가리키는 포인터 변수에서 j번째 원소를 가리키는 포인터 변수를 빼면 결과는 i-j 가 된다. 실행 결과 short sArrays[10]; short* ps1 = &sArrays[3]; short* ps2 = &sArrays[7]; // 결과를 출력한다. cout << "ps1 = " << ps1 << "\n"; cout << "ps2 = " << ps2 << "\n"; cout << "ps2 - ps1 = " << ps2 - ps1 << "\n"; [그림 12-6] [그림 12-5]

17 포인터를 사용한 원소의 탐색 일반적인 방법을 사용한 원소의 탐색 포인터를 사용한 원소의 탐색 int nArray[10];
// 배열을 탐색하면서 값을 넣는다. for (int i = 0; i < 10; ++i) nArray[i] = i; int nArray[10]; int* p = &nArray[0]; // 배열을 탐색하면서 값을 넣는다. for (int i = 0; i < 10; ++i) *(p + i) = i;

18 배열의 이름 배열의 이름은 첫번째 원소의 주소가 된다. 배열의 이름을 사용해서 배열을 탐색하는 예 float f[5];
if ( f == &f[0] ) { // 항상 이곳이 실행된다. } int nArray[10]; // 배열을 탐색하면서 값을 넣는다. for (int i = 0; i < 10; ++i) *(nArray + i) = i;

19 배열을 가리키는 포인터 배열의 원소가 아닌 배열 전체를 포인터 변수로 가리키는 예 실행 결과 long lArray[20];
// 포인터가 이 배열을 가리키게 만들자 long (*p)[20] = &lArray; // 포인터를 통해서 배열을 사용하자. (*p)[3] = 300; // 결과를 확인하자 cout << "lArray[3] = " << lArray[3] << "\n"; [그림 12-7]

20 연산자 우선순위 배열을 가리키는 포인터 변수의 정의 배열을 가리키는 포인터 변수의 사용 [그림 12-8] [그림 12-9]

21 포인터의 배열 포인터 변수의 배열을 정의하는 예 // 참조될 변수들을 정의한다. double a, b, c;
// 3개의 원소를 가진 포인터의 배열을 정의한다. double* pArray[3]; // 각 원소가 변수들을 가리키도록 만든다. pArray[0] = &a; pArray[1] = &b; pArray[2] = &c;

22 배열을 포함하는 구조체 배열을 멤버로 갖는 구조체의 예 실행 결과 struct StudentInfo {
char name[20]; // 이름 int stdNumber; // 학번 float grade[2]; // 최근 2학기 평점 }; StudentInfo si = { "Kim Chol-Su", , {3.2f, 3.5f} }; cout << si.name << "\n"; cout << si.stdNumber << "\n"; cout << si.grade[0] << ", " << si.grade[1] << "\n"; [그림 12-11]

23 구조체의 배열 구조체 변수의 배열을 정의하는 예 struct StudentInfo { char name[20]; // 이름
int stdNumber; // 학번 float grade[2]; // 최근 2학기 평점 }; StudentInfo stdInfos[5] = { { "Kim Chol-Su", , {3.2f, 3.5f} }, { "Lee Chol-Su", , {4.5f, 4.5f} }, { "Park Chol-Su", , {1.7f, 2.0f} }, { "Yang Chol-Su", , {0.4f, 4.1f} }, { "Yoon Chol-Su", , {2.7f, 2.8f} } [그림 12-14]

24 구조체를 가리키는 포인터 구조체 변수를 가리키는 포인터를 정의하는 예 실행 결과 struct Rectangle {
int x, y; int width, height; }; Rectangle rc = { 100, 100, 50, 50}; // 포인터가 이 변수를 가리키게 만든다. Rectangle* p = &rc; // 구조체의 멤버에 접근한다. (*p).x = 200; p->y = 250; cout << "rc = ( " << rc.x << ", " << rc.y << ", "; cout << rc.width << ", " << rc.height << ")\n"; [그림 12-15]

25 포인터를 포함하는 구조체 포인터 변수를 멤버로 갖는 구조체를 정의하는 예 실행 결과 struct Dizzy {
int id; // 구조체 변수마다 갖는 고유한 값 Dizzy* p; // Dizzy 구조체를 가리키는 포인터 }; // Dizzy 객체를 3개 만들고, 서로를 가리키도록 만든다. Dizzy a, b, c; a.id = 1; a.p = &b; b.id = 2; b.p = &c; c.id = 3; c.p = &a; // a 만 사용해서 a, b, c 모두에 접근한다. cout << "a.id = " << a.id << "\n"; cout << "b.id = " << a.p->id << "\n"; cout << "c.id = " << a.p->p->id << "\n"; cout << "a.id = " << a.p->p->p->id << "(again)\n"; [그림 12-17] [그림 12-16] 그림 넣을 공간이 부족하기는 하지만 잘 맞춰서 넣어봐.. ㅎㅎ

26 01_ 나머지 복합 타입들 02_ 배열, 구조체, 포인터의 나머지 기능
13장. 복합 타입의 모든 것 01_ 나머지 복합 타입들 02_ 배열, 구조체, 포인터의 나머지 기능

27 공용체(Unions) 공용체의 모든 멤버는 같은 메모리 공간을 공유한다. union ManyMembers { char c;
short s; int i; float f; double d; }; [그림 13-3]

28 공용체의 사용 공용체의 멤버가 같은 공간을 공유한다는 점을 확인하는 예 실행 결과 union MyUnion { int i;
void* p; }; MyUnion uni; cout << "&uni.i = " << &uni.i << "\n"; cout << "&uni.p = " << &uni.p << "\n"; uni.i = 0x ; cout << hex; cout << "uni.i = " << uni.i << "\n"; cout << "uni.p = " << uni.p << "\n"; uni.p = (void*)0x ; [그림 13-2]

29 열거체(Enumerations) 열거체를 사용해서 상수값에 대한 심볼을 정의하는 예
enum JOB_KINDS { JOB_DWARF, JOB_WARRIOR, JOB_SORCERER }; struct Character { JOB_KINDS jobType; // 다른 멤버들이 더 있다. }; Character c; // c 가 누군가에 의해 초기화 된다. // c가 마법사인 경우 if (JOB_SORCERER == c.jobType) // 필요한 일을 한다. }

30 열거체와 심볼의 값 열거체의 심볼들은 자동적으로 0 기반의 인덱스 값을 갖는다. =
열겨체의 심볼에 값을 대입한 경우, 뒤쪽의 심볼들은 해당 값을 기반으로 증가한다. enum { JOB_DWARD, JOB_WARRIOR, JOB_SORCERER }; = enum { JOB_DWARD = 0, JOB_WARRIOR = 1, JOB_SORCERER = 2}; enum { JOB_DWARD, JOB_WARRIOR = 3, JOB_SORCERER }; = enum { JOB_DWARD, JOB_WARRIOR = 3, JOB_SORCERER = 4};

31 열거체와 정수 타입 열거체를 사용해서 산술 연산을 할 수 없다. 정수를 열거체 변수에 대입할 수 없다.
열거체의 심볼들은 암시적으로 정수 타입으로 형변환 된다. 명시적인 형변환을 사용해서 정수 타입의 값을 열거체 변수에 담을 수 있다. enum Color { RED, BLUE, GREEN, SKYBLUE, MAGENTA, YELLOW }; Color color1 = RED; color1 = SKYBLUE + YELLOW; // Error Color1 += 3; // Error Color color2; color2 = 5; // Error int n = MAGENTA; // n 은 4가 된다. int m = BLUE + 2; // m 은 3이 된다. Color color3 = (Color)2 // color3은 GREEN이 된다. Color color4 = (Color)5000 // 결과를 알 수 없다.

32 레퍼런스(References) 레퍼런스 변수를 사용해서 변수의 별칭을 만드는 예 int target = 20;
// 레퍼런스 변수를 정의한다. int& ref = target; cout << "ref = " << ref << "\n"; cout << "target = " << target << "\n"; cout << "&ref = " << &ref << "\n"; cout << "&target = " << &target << "\n"; // ref의 값을 바꿔보자. ref = 100; [그림 13-4]

33 레퍼런스 변수의 초기화 레퍼런스 변수의 초기화와 대입은 다른 의미를 갖는다. // 변수를 정의한다.
float a = 100.0f; float b = 12.34f; // r을 a에 대한 별명으로 만든다. (초기화) float& r = a; // r에 200.0f를 대입한다. (대입) r = 200.0f; // r에 b의 값 12.34f를 대입한다. (대입) r = b; // r에 56.7f를 대입한다. (대입) r = 56.7f

34 레퍼런스 변수와 Const Const 속성을 가진 레퍼런스 변수만 상수로 초기화할 수 있다.
const int& rci = 100; // OK int& ci = 100; // Error [그림 13-7] char c = ‘A’; const int& rci = c; // OK int& ci = c; // Error [그림 13-8]

35 typedef typedef를 사용해서 타입의 별칭의 만드는 예 typedef unsigned char* uc_ptr;
unsigned char uc = ‘A’; uc_ptr p = &uc; [그림 13-9]

36 비트 필드(Bit Fields) 구조체의 멤버 변수들이 차지하는 비트 수를 지정하는 예 struct Flags {
int a : 3; int b : 4; int : 5; // 이 5비트는 쓰지 않는다. bool c : 1; }; [그림 13-11]

37 구조체를 포함하는 구조체 구조체 변수를 멤버로 갖는 구조체를 정의하는 예 struct A { int i; float f; };
struct B char c; A a; [그림 13-14]

38 다차원 배열 다차원 배열 (= 배열의 배열)을 정의하는 예
좌측의 그림은 이해하기 편하게 그린 것이고, 우측의 그림은 실제로 다차원 배열이 메모리에 자리잡는 모습을 그린 것이다. int arr[10][5]; // 배열의 모든 원소에 10을 대입한다. for ( int i = 0; i < 10; ++i ) { for ( int j = 0; j < 5; ++j ) arr[i][j] = 10; } [그림 13-15] [그림 13-16]

39 포인터를 가리키는 포인터 포인터 변수를 가리키는 포인터 변수를 정의하는 예 char c = ‘1’; char* pc = &c;
char** ppc = &pc; if ( *ppc == pc ) { // 이곳은 항상 실행된다. } if ( **ppc == c ) [그림 13-17]


Download ppt "11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const."

Similar presentations


Ads by Google