6.1 Addresses and Pointers Recall memory concepts from Ch2 ch6_testbasicpointer.c int x1=1, x2=7; double distance; int *p; int q=8; p = &q; name addre

Save this PDF as:
 WORD  PNG  TXT  JPG

Size: px
Start display at page:

Download "6.1 Addresses and Pointers Recall memory concepts from Ch2 ch6_testbasicpointer.c int x1=1, x2=7; double distance; int *p; int q=8; p = &q; name addre"

Transcription

1 GEN1031 Computer Programming Chapter 6 Pointer 포인터 Kichun Lee Department of Industrial Engineering Hanyang Univesity 1

2 6.1 Addresses and Pointers Recall memory concepts from Ch2 ch6_testbasicpointer.c int x1=1, x2=7; double distance; int *p; int q=8; p = &q; name address x1 x2 distance p q Memory - content 1 = = ? = arbitrary 1 s and 0 s????

3 포인터란? 포인터는메모리위치의주소를보유한변수이다. 변수 p가다른변수q의주소를보유한다면, p는 q를가리킨다. 만약 q가메모리위치 16에있는변수라면, p의값은16이다.(16는변수 q의주소 ) 3

4 포인터변수선언방법 포인터변수는이름앞에별표 * 를사용하여선언한다. int a, b, *ptr; Ptr은 integer를저장할수있는메모리위치에대한포인터 4

5 주소연산자 : & 변수는주소연산자 & 를사용하여참조될수있다. 이전예제 (2p): &x1 는 x1의주소이다. printf( %d, &x1); will print 12 (address) printf( %d, x1); will print 1 (content) 5

6 * 는상황에따라다른의미를가진다. a = x * y; multiplication int *ptr; declare a pointer C언어에서 * 는 indirection 또는 dereferencing 연산자로도사용된다. ptr = &y; a = x * *ptr; 6

7 Example: Pointers, address, indirection ch6_testbasicpointer2.c int a, b; int *c, *d; a = 5; c = &a; d = &b; *d = 9; print c, *c, &c print a, b name address memory a b c ???? c=11 *c=5 &c=13 a=5 b= d 12 7

8 Exercise: Trace the following code ch6_testbasicpointer3.c name address memory int x, y; int *p1, *p2; x = 3 + 4; Y = x / 2 + 5; p1 = &y; p2 = &x; *p1 = x + *p2; *p2 = *p1 + y; print p1, *p1, &p1 print x, &x, y, &y x y p1 p ???? 8

9 MORE ABOUT POINTERS DECLARATION, ASSIGNMENT, COMPARISON, TYPE, ARITHMETIC 9

10 포인터선언 int *p, q; 형식을사용할때, * 연산자는분배되지않는다. 위의예제에서 p 는 int 의포인터로선언됨 q 는 int 로선언됨 만약 p, q 모두포인터로원할경우, int *p, *q; 10

11 포인터에값할당 int a; int *iptr; 위의예제에서변수들은초기화되지않는다. 대입연산자 (=) 는포인터를정의한다. 우변은좌변과같은타입이면어떤표현으로도나타낼수있다. 일반변수앞의 & 연산자는그변수의주소를생성한다. a = 4 + 5; iptr = &a; 11

12 Exercise Give a memory snapshot after each set of assignment statements int a=1, b=2, *ptr; ptr = &b; a = *ptr; *ptr = 5; a 102 b 104 ptr

13 NULL 포인터 포인터는 integer zero와비교하여기호상수 NULL로할당될수있다. (NULL은 <stdio.h> 에정의되어있음 ) NULL 값을가지는포인터변수는엑세스가능한어떤것도가리키지않는다. 13

14 포인터초기화 ch6_testbasicpointer4.c iptr int *iptr=0; char *s=0; s double *dptr=null; dptr!!! 우리포인터가선언되는동안포인터에값을할당할때, 포인터변수에그값을넣기를의도한다. (no indirection)!!! int *iptr=0; is same as int *iptr; iptr=0; /* not like *iptr = 0; */ 14

15 Many-to-One Pointing 포인터는한번에하나의위치를가리킬수있지만, 여러개의포인터는동일한위치를가리킬수있다. /* Declare and initialize variables. */ int x=-5, y = 8; int *ptr1, *ptr2; x /* Assign both pointers to point to x. */ ptr1 = &x; ptr2 = ptr1; The memory snapshot after these statements are executed y Ptr ptr

16 Exercise Show the memory snapshot after the following operations int x=2, y=5, temp; int *ptr1, *ptr2, *ptr3; 2 5? // make ptr1 point to x ptr1 = &x; x y temp // make ptr2 point to y ptr2 = &y; ptr1 ptr2 ptr3 16

17 Exercise Show the memory snapshot after the following operations // swap the contents of // ptr1 and ptr2 2 5? ptr3 = ptr1; x y temp ptr1 = ptr2; ptr2 = ptr3; ptr1 ptr2 ptr3 17

18 Exercise Show the memory snapshot after the following operations // swap the values pointed // by ptr1 and ptr temp = *ptr1; x y temp *ptr1 = *ptr2; *ptr2 = temp; ptr1 ptr2 ptr3 18

19 포인터비교 >,<,== etc 사용하여포인터를비교할수있다. 일반적인비교 : null pointer 인지확인 if (p == NULL) 두포인터가같은위치를가리키는지확인 if (p == q) 이것은아래와같은가? if (*p == *q) 다음식의의미는 if (*p == *q) p 와 q 에의해가리켜지는두값을비교하는것 19

20 포인터타입 포인터선언하는것은주소를보유할수있는변수를생성하는것이다. 주소는 integers! 그러나, 포인터의선언에서우리가지정하는타입은포인터가가리키는변수의타입이다.!!!integer 를가리키도록선언된포인터는 float/double 변수를가리킬수없다. float/double 변수가 integer 주소를보유하더라도!!! 20

21 Example: 다른타입의포인터 int a=5; double b=23.452; int *iptr; double *dptr; iptr = &a; dptr = &b; a 102 b 106 iptr 114 dptr the variable iptr is declared to point to an int the variable dptr is declared to point to a double

22 6.4 함수참조에서포인터 (! 중요!) C 에서, 함수참조는배열이름이인수로사용될때를제외하고는 call-by-value 이다. 배열이름은첫번째성분의주소이다. 배열의값은함수내 statements 로수정할수있다. 함수의인수를수정하기위해서, 인수에대한포인터가전달되어야한다. scanf( %f, &X); 이문장은입력받은값이 X 의주소에저장되도록한다. 포인터인수에해당하는실제파라미터는반드시주소또는포인터여야한다. 22

23 Call by Value void swap(int a,int b) { int temp; temp = a; a = b; b = temp; main() { int x = 2, y = 3; printf("%d %d\n,x,y); swap(x,y); } return; printf("%d %d\n,x,y); } Swap 함수에서변경은함수실행이끝날때사라진다. 함수실행후 x, y 변화없음 23

24 Call by reference test_swap.c void swap2(int *aptr, int *bptr) { int temp; main() { int x = 2, y = 3; } temp = *aptr; *aptr = *bptr; *bptr = temp; return; printf("%d %d\n,x,y); swap2(&x, &y); printf("%d %d\n,x,y); } swap 함수에의한변경은원래 x, y 값에도적용된다. 그래서함수실행이끝나면 x, y 값이변한다. 24

25 Trace a program main() { int x0=5, x1=2, x2=3; int *p1=&x1, *p2; p2 = &x2; swap2(&x0, &x1); swap2(p1, p2); printf( %d %d %d\n, x0, x1, x2); } void swap2(int *a, int *b) { int tmp; Name Addr Value x0 1 x1 2 x2 3 p1 4 p2 5 6 a 7 } tmp = *a; *a = *b; *b = tmp; return; b 8 tmp 9 25

26 이제함수에서하나이상의값을 얻을수있다. 이차방정식 ax^2+bx+c=0 의해를구하는함수를작성해라. 해는어떻게반환하는가? void comproots(int a,int b,int c, double *dptr1, double *dptr2) { *dptr1 = (-b - sqrt(b*b-4*a*c))/(2.0*a); *dptr2 = (-b + sqrt(b*b-4*a*c))/(2.0*a); return; } 26

27 test_2ndpoly.c Exercise cont d main() { int a,b,c; double root1,root2; printf("enter Coefficients:\n"); scanf("%d %d %d",&a,&b,&c); comproots(a,b,c,&root1,&root2); } printf("first Root = %lf\n",root1); printf("second Root = %lf\n",root2); 27

28 Trace a program main() { int x, y; max_min(4, 3, 5, &x, &y); printf( First: %d %d, x, y); max_min(x, y, 2, &x, &y); printf( Second: %d %d, x, y); } void max_min(int a, int b, int c, int *max, int *min) { *max = a; *min = a; if (b > *max) *max = b; if (c > *max) *max = c; if (b < *min) *min = b; if (c < *min) *min = c; printf( F: %d %d\n, max, *max); } name Addr Value x 1 y a 6 b 7 c 8 max 9 min 10 28

29 추가자료 29

30 포인터연산 사칙연산이지원된다. +, -, ++, -- 오직 integers 만사용될수있다. 연산은가리켜지는변수에대해서수행된다. 대부분배열과함께사용 ( 다음장 ) Example: p++; p가 int *p로정의되면, p는 4 증가한다. (system dependent) p가 double *p 로정의되면, p는 8 증가한다. (system dependent) 포인터에서 ++ 는포인터가메모리에서다음위치를가리키는것을의미한다. 30

31 6.2 포인터와배열 int main_pointarray(void) 배열의이름은첫번째성분의주소이다. (i.e. a pointer to the first element) 배열의이름은항상배열의첫성분을가리키고, 그값은변하지않으므로상수다. 배열의이름과포인터두단어는종종교체사용된다. Example int num[4] = {1,2,3,4}, *p, *q; p = num; q = p; // or q = num; /* above assignment is the same as p = &num[0]; */ printf( %i, *p); // print num[0] p++; printf( %i, *p); // print num[1] printf( %i, *q); // print num[0] printf( %i, *(p+2)); // print num[2] 31

32 포인터와배열 (cont d) 배열표기법을사용하여포인터를 index할수있다. char string[] = This is a string ; char *str; int i; str = string; for(i =0; str[i]!=null; i++) printf( %c, str[i]); 32

33 2 차원배열 2 차원배열은행순서에따라메모리위치에순차적으로저장된다. int s[2][3] = {{2,4,6}, {1,5,3}}; int *sptr = &s[0][0]; Memory allocation: s[0][0] 2 s[0][1] 4 s[0][2] 6 s[1][0] 1 s[1][1] 5 s[1][2] 3 A pointer reference to s[0][1] would be *(sptr+1) A pointer reference to s[1][1] would be *(sptr+4) row offset * number of columns + column offset 33

34 Exercise Study Section 6.3 from the textbook 34

35 6.7 동적메모리할당 동적으로할당된메모리는 runtime 시결정된다. 프로그램은필요한만큼몇가지변수를만들수있고더큰유연성을제공한다. 동적할당은종종 stacks, queues, linked lists and binary trees 같은데이터구조를지원하는데사용된다. 동적메모리는유한하다. 동적으로할당된메모리는실행중에해제될수있다. 35

36 동적메모리할당 메모리할당방법 : malloc function (memory allocation) calloc function (cleared memory allocation) 메모리해제방법 : free function The size of memory requested by malloc 또는 calloc 에의해필요한메모리사이즈변경방법 : realloc function 36

37 malloc and calloc 두함수모두새로할당된메모리에대한포인터반환 메모리가할당될수없으면 NULL 값반환 이러한함수에의해반환된포인터는 void pointer 로선언된다. cast 연산자는반환된포인터값과함께사용되어야한다. 37

38 Example of malloc and calloc ch6_returnstacktest.c int n = 6, m = 4; double *x; int *p; X /* Allocate memory for 6 doubles. */ x = (double *)malloc(n*sizeof(double)); /* Allocate memory for 4 integers. */ p = (int *)calloc(m,sizeof(int)); p 38