C Programming 포인터 (Pointers) Seo, Doo-Ok Clickseo.com clickseo@gmail.com
목 차 포인터의이해 다양한포인터 2
포인터의이해 포인터의이해 포인터변수선언및초기화 포인터연산 다양한포인터 3
주소연산자 ( & ) 포인터의이해 (1/4) 변수와배열원소에만적용한다. 산술식이나상수에는주소연산자를사용할수없다. 레지스터변수또한주소연산자를사용할수없다. &100; // 상수에는주소연산자를사용할수없다. &(a+1) // 산술식에는주소연산자를사용할수없다. register a; // 레지스터변수에는주소연산자를사용할수없다. #include <stdio.h> int a; &a; int main(void) { int a; int b; printf( %p %p n, &a, &b); } return 0; 4
포인터의이해 (2/4) 포인터변수 (pointer variable) 포인터 메모리주소에대한기호화된표현 int *p; 포인터변수 : 메모리주소를를저장할수있는변수 간접연산자 ( * ) 또는역참조연산자 포인터변수에저장된주소를참조하여대상체의크기 ( 자료형 ) 만큼메모리를간접접근한다. 포인터변수는메모리주소이외에는 어떠한값도저장하지않는다는것을절대잊으면안된다. 5
포인터의이해 (3/4) 포인터변수 : 물리적 / 논리적표현 물리적인표현과논리적인표현 a 10 0x0012FF70 10 a p 0x0012FF70 p 6
포인터변수 : 다중포인터 변수에대한다중포인터 포인터의이해 (4/4) pa 0x0012FF70 a 100 0x0012FF70 &a pb 0x0012FF70 7
포인터의이해 포인터변수선언및초기화 8
포인터변수선언및초기화 (1/5) 포인터변수의선언및초기화 초기화되지않은변수와포인터 int a; int *p; a??? 포인터변수의초기화 p??? int a = 10; int *p = &a; int *p; 포인터형변수선언 p = &a; 포인터형변수초기화 9
포인터변수선언및초기화 (2/5) 포인터변수에왜자료형을지정하는가? // 컴파일러는아래문장을어떻게처리할까? // 즉, 메모리에몇바이트씩을할당할까? char int float double *pc; *pi; *pf; *pd; 포인터변수는항상 4 바이트메모리가할당된다. Data Type : unsigned int 포인터변수의자료형은포인터변수가가리키는대상체의크기 ( 자료형 ), 즉, 저장하고있는메모리주소를간접접근하여 어떤형태 ( 자료형 ) 로접근 ( 해석 ) 할것인가를의미한다. 10
포인터변수선언및초기화 (3/5) 포인터변수를통한변수접근 : 간접접근방법 // 변수와포인터변수선언 int a; int *p; p a 0x0012FF70 10 0x0012FF78 0x0012FF70 // 변수와포인터변수의초기화 a = 10; p = &a; *p a 10 // 변수 a 의데이터값 p &a 0x0012FF70 // 변수 a 의주소 a = a + 1; a++; *p = *p + 1; (*p)++; 11
포인터변수선언및초기화 (4/5) 예제 3-1 : 포인터변수의메모리크기 Visual Studio Community 2017 #include <stdio.h> int main(void) { char *pc; int *pi; float *pf; double *pd; printf("char * : %d \n", sizeof(char *) ); printf("int * : %d \n", sizeof(int *) ); printf("float * : %d \n", sizeof(float *) ); printf("double * : %d \n", sizeof(double *) ); } return 0; 12
포인터변수선언및초기화 (5/5) 예제 3-2 : 포인터변수의메모리크기 GCC(GNU Compiler Collection) #include <stdio.h> int main(void) { char *pc; int *pi; float *pf; double *pd; // warning: format '%d' expects argument of type 'int, // but argument 2 has type 'long unsigned int // printf("char * : %d \n", sizeof(char *) ); printf("char * : %ld \n", sizeof(char *) ); printf("int * : %ld \n", sizeof(int *) ); printf("float * : %ld \n", sizeof(float *) ); printf("double * : %ld \n", sizeof(double *) ); } return 0; 13
포인터변수선언및초기화 (4/5) 예제 3-3 : 포인터변수의선언및초기화그리고간접접근 #include <stdio.h> p a int main(void) { int a; int *p; 0x0012FF7C 14 0x0012FF70 0x0012FF7C a = 14; p = &a; printf( a : %d, &a : %p\n", a, &a ); printf( p : %p, *p : %d, a : %d \n", p, *p, a ); } return 0; 14
포인터변수선언및초기화 (5/5) 예제 3-4 : 일반변수의직접접근과포인터변수의간접접근 #include <stdio.h> int main(void) { int a, b, c; int *pa, *pb, *pc; a = 6; b = 2; pa = &b; pb = pa; pc = &c; pa = &a; *pb = 8; *pc = *pa; *pc = a + *pb + *&c; printf("a : %d, b : %d, c : %d \n", a, b, c ); printf("*pa : %d, *pb : %d, *pc : %d \n", *pa, *pb, *pc ); } return 0; 15
포인터의이해 포인터연산 16
포인터연산 (1/3) 포인터연산 연산의대상 : 메모리주소 정수연산만가능 사용가능연산자 : +, -, ++, --, >, >=, <, <=, ==,!= 포인터가가리키는대상체 ( 자료형 ) 의크기만큼연산이일어난다. int a = 10; int *p; p = &a; p++; // 실제로증가되는대상은? 17
예제 3-5 : 포인터연산 - 증감연산자 #include <stdio.h> 포인터연산 (2/3) int main(void) { int a = 10; int *p; p = &a; printf("a : %d, p : %p \n", a, p ); p++; printf("a : %d, p : %p \n", a, p ); } return 0; 18
#include <stdio.h> 포인터연산 (3/3) 예제 3-6 : 포인터연산 - 간접연산자와증감연산자 int main(void) { int a = 10; int *p; p = &a; printf("a : %d, p : %p \n", a, p ); (*p)++; printf("a : %d, p : %p \n", a, p ); } return 0; 19
다양한포인터 포인터의이해 다양한포인터 void 포인터 NULL 포인터 다중포인터 20
void 포인터 (1/6) void 포인터 어떤대상체 ( 자료형 ) 의메모리주소든지저장할수있는포인터 포인터변수선언시간접접근방법을지정하지않은포인터 간접접근으로대상체의메모리를접근할때는반드시형변환이이루어져야한다. p char void *p; int double 21
void 포인터 (2/6) void 포인터변수 : 다양한자료형의메모리주소저장 1. 어떠한형변환없이도 void 포인터변수에메모리주소의저장이가능하다. #include <stdio.h> int main(void) { char c; int i; float f; double d; void *p; #include <stdio.h> int main(void) { char c; int i; p = &c; p = &i; p = &f; p = &d; int *p; // warning C4133: '=' : incompatible types - from 'char *' to 'int *' p = &c; --> p = (int *)&c; p = &i; } return 0; } return 0; 22
void 포인터 (3/6) void 포인터변수 : 다양한포인터의값 ( 메모리주소 ) 저장 #include <stdio.h> int main(void) { char *pc; int *pi; float *pf; double *pd; } void p = pc; p = pi; p = pf; p = pd; return 0; *p; #include <stdio.h> int main(void) { char int } int *pc; *pi; *p; // warning C4133: '=' : incompatible types - from 'char *' to 'int *' p = pc; --> p = (int *)pc; p = pi; return 0; 23
void 포인터 (4/6) void 포인터변수 : 포인터변수와형변환 2. void 포인터변수를이용하여일반변수의값을읽을때는반드시형변환이이루어져야한다. #include <stdio.h> int main(void) { char c = A ; int i = 5; double d = 0.7; void *p; p = &c; printf("c : %c \n", *(char *)p ); p = &i; printf("i : %d \n", *(int *)p ); p = &d; printf("d : %.1f \n", *(double *)p ); } return 0; 24
void 포인터 (5/6) void 형포인터변수 : 간접접근과대상체의크기 ( 자료형 ) 3. 간접연산자를사용할때는포인터변수가저장하고있는메모리주소의대상체의크기 ( 자료형 ) 과일치해야한다. int i = 5; void *p; // 정수형변수 i 의메모리주소를포인터변수 p 에저장한다. p = &i; // 포인터변수 p 가가리키고있는메모리영역을 int 형식 (4bytes) 으로읽어야한다. printf("i : %f \n", *(double *)p ); <-- 무의미!!! printf( i : %d n, *(int *) p ) ; 25
void 포인터 (6/6) void 형포인터변수 : 간접접근과증감연산자 4. void 형포인터변수에 ++, -- 를사용할때에는항상형변환이이루어져야한다. ++ 나 -- 를사용하려면정확한대상체의크기 ( 자료형 ) 을알아야그크기만큼의정확한연산이이루어진다. 정확한대상체의크기 ( 자료형 ) 을명시하지않으면, 컴파일러는어떤형태로간접접근할지를알수없기때문에문제가발생한다. #include <stdio.h> int main(void) { int i = 50; void *p; *(int *) p = *(int *) p + 1; ( *(int *) p )++; p = &i; // *p = *p + 1; (*p)++; // error C2036: 'void *' : unknown size } return 0; 26
다양한포인터 NULL 포인터, 다중포인터 27
NULL 포인터 NULL 포인터 매크로상수 : 널포인터상수 #define NULL (void *) 0 #include <stdio.h> // NULL int main(void) { // NULL 포인터 int *ptr = NULL; printf("ptr : %u", ptr ); } return 0; 28
다중포인터 (1/2) 이중포인터 (Double Pointer) 포인터에대한포인터 ppa pa a 0x0012FF70 0x0012FF7C 10 0x0012FF64 0x0012FF70 0x0012FF7C int a; int *pa; int **ppa; a = 10; pa = &a; ppa = &pa; printf("%3d", a ); printf("%3d", *pa ); printf( %3d, **ppa ); 29
예제 3-7 : 이중포인터 #include <stdio.h> 다중포인터 (2/2) int main(void) { int a = 10; int *pa; int **ppa; pa = &a; ppa = &pa; printf("a : %d, &a : %p \n", a, &a ); printf("*pa : %d, pa : %p \n", *pa, pa ); printf("**ppa : %d, *ppa : %p \n", **ppa, *ppa ); } return 0; 30
참고문헌 [1] 서두옥, 이동호 ( 감수 ), ( 열혈강의 ) 또하나의 C : 프로그래밍은셀프입니다, 프리렉, 2012. [2] Paul Deitel, Harvey Deitel, "C How to Program", Global Edition, 8/E, Pearson, 2016. [3] SAMUEL P. HARBISON Ⅲ, GUY L. STEELE, C 프로그래밍언어, C : A Reference Manual, 5/E, Pearson Education Korea, 2005. [4] Behrouz A. Forouzan, Richard F. Gilberg, 김진외 7인공역, 구조적프로그래밍기법을위한 C, 도서출판인터비젼, 2004. [5] Brian W. Kernighan, Dennis M. Ritchie, 김석환외 2인공역, The C Programming Language, 2/E, 대영사, 2004. [6] 김일광, C 프로그래밍입문 : 프로그래밍을모국어처럼유창하게, 한빛미디어, 2004. [7] 정재은, " 다시체계적으로배우는 C 언어포인터 ", 정보문화사, 2003. 이강의자료는저작권법에따라보호받는저작물이므로무단전제와무단복제를금지하며, 내용의전부또는일부를이용하려면반드시저작권자의서면동의를받아야합니다. Copyright Clickseo.com. All rights reserved. 31