336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
포인터의 값의 변화를 알기 위한 예제이다.
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 | #include<stdio.h> void func(int A, int B, int *x, int *y){ A = B + 100; *x = B + 200; B++; y = y + 100; printf("<func> (A) %d (B) %d (*x) %d (*y) %d \n", A, B, *x, *y ); } int main(int argc, char** argv){ int a = 100; int b = 300; int *ptr1 = &a; int *ptr2 = &b; int *ptr3; printf("<1> (a) %d (b) %d (*ptr1) %d (*ptr2) %d \n", a, b, *ptr1, *ptr2 ); *ptr1 = 10; *ptr2 = *ptr1; (*ptr2)++; ptr3 = ptr1; *ptr3 = *ptr3 + 50; ptr3++; printf("<2> (a) %d (b) %d (*ptr1) %d (*ptr2) %d \n", a, b, *ptr1, *ptr2 ); func(a, b, ptr1, ptr2); printf("<3> (a) %d (b) %d (*ptr1) %d (*ptr2) %d \n", a, b, *ptr1, *ptr2 ); return 0; } | cs |
위 코드를 실행시키면 각 출력문은 무엇을 출력하는지 알아보자.
출력순서는 코드 진행순서대로 메인함수 <1>,<2> , 함수호출 <func> , 다시 메인함수로 돌아와 <3> 을 출력하고 종료한다.
함수부터 알아보자면,
1 2 3 4 5 6 7 | void func(int A, int B, int *x, int *y){ A = B + 100; *x = B + 200; B++; y = y + 100; printf("<func> (A) %d (B) %d (*x) %d (*y) %d \n", A, B, *x, *y ); } | cs |
함수의 이름은 func 이고, 반환값 형(타입)은 값이 없는 'void' 이다. 함수의 인자(parameter)는 int형인 A, B, int 포인터형인 x, y 로 정의 하고 다음은 body block 이다. 함수를 실행하면 스택메모리 영역에 함수가 호출되고, 각 인자들은 함수의 스택메모리 영역에 자리를 차지한다. 내부에 선언된 변수가 없으므로, 해당 함수에는 총 4개의 지역변수가 존재한다.
1 2 3 4 5 6 7 8 9 10 11 | int main(int argc, char** argv){ int a = 100; int b = 300; int *ptr1 = &a; int *ptr2 = &b; int *ptr3; printf("<1> (a) %d (b) %d (*ptr1) %d (*ptr2) %d \n", a, b, *ptr1, *ptr2 ); //.. } | cs |
처음 메인함수가 실행되면 int형인 변수 a 에 100 의 값을 초기화하고, 변수 b는 300을 초기화 한다. 이후 int형 포인터 ptr1, ptr2, ptr3 을 선언하고 ptr1은 a의 주소값인 (&a) 로 초기화, ptr2는 변수 b의 주소값인 (&b)를 초기화 값으로 담는다. ptr3은 변수 선언만 한다.
그러면 출력문 1번에서는 a 값은 100, b의 값은 300, ptr1 이 저장한 주소를 참조한 값인 100, ptr2가 저장한 주소를 참조한 값인 300을 출력하게 된다.
위 단계에서 저장된 값은
a = 100;
b = 300;
ptr1 = &a;
ptr2 = &b;
을 각각 저장되어있다. 아래 코드 진행을 보면
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int main(int argc, char** argv){ //.. *ptr1 = 10; *ptr2 = *ptr1; (*ptr2)++; ptr3 = ptr1; *ptr3 = *ptr3 + 50; ptr3++; printf("<2> (a) %d (b) %d (*ptr1) %d (*ptr2) %d \n", a, b, *ptr1, *ptr2 ); //.. } | cs |
ptr1 가 저장하고 있는 주소를 참조한 값을 10으로 변경한다. *ptr = 10; , 이는 *(&a) = 10; 이 문장을 뜻하며, 의미상 a = 10; 으로 봐도 될 것 같다. 그래서 a 에 저장하고 있는 값은 10이 된다.
*ptr2 = *ptr1; 은 ptr1이 저장한 주소에 값을 참조하고 ptr2 가 저장한 주소에 값을 참조하여 값을 넣는다는 의미이다. *(&b) = *(&a); 라는 의미가 되며 b = a; 라는 의미와 같다. a 에 저장되어 있는 값이 앞선 문장에서 10이기 때문에 b에는 10이 저장된다.
이후 (*ptr2)++; 는 후위연산자를 사용해서 해당 라인을 실행한 후에 +1 을 한다.
그리고 ptr3 = ptr1; 는 ptr3이 저장하는 주소 값을 ptr1 이 저장한 주소값을 대입한다.
*ptr3 = *ptr3 + 50; 은 위 문장에서 ptr1의 주소를 저장하여, *(&a) = *(&a) + 50; 즉, a = a +50; 의 의미와 같다. 원래 a 에 저장되어있는 값인 10 에 + 50 을 하여 a 에 저장한다.
이후 ptr3++; ptr3에 저장되어 있는 주소 값을 주소의크기만큼 1칸 이동한다. 운영체제에 따라 32비트 는 4바이트, 64비트 8바이트의 주소크기를 갖는다.
출력문에서는 a는 60, b는 11, *ptr1 60, *ptr2 11 을 출력한다.
1 2 3 4 5 6 7 8 9 10 11 | int main(int argc, char** argv){ // a 60; // b 11; // ptr1 &a; // ptr2 &b; func(a, b, ptr1, ptr2); printf("<3> (a) %d (b) %d (*ptr1) %d (*ptr2) %d \n", a, b, *ptr1, *ptr2 ); return 0; } | cs |
위 단계에서의 값을 주석으로 정리해 두었다. ptr1,2 가 저장하고(가리키고) 있는 주소 값은 변함이 없고, 변수 a 는 60, b는 11을 저장하고 있다.
이후 func함수를 호출 하면 (a, b, ptr1, ptr2); 로 인자를 넣는다.
call by value 로 값에 의한 호출과 call by reference(address) 로 호출하여 사용한다.
call by value 로 선언된 값은 값에 의한 호출로 main 함수가 인자로 준 것에 호출한 func 함수가 변수값을 변화 시킬 수 없다.
call by reference는 메인함수에 선언된 변수에 주소값을 넘겨주는 것이므로 직접적으로 값을 변경할 수 있다.
1 2 3 | void func(int A, int B, int *x, int *y){ //.. } | cs |
이때 ptr1, ptr2 와 func의 x, y 는 다른 것이며, 같은 것으로 보면 안된다. 값을 저장하는 변수가 func안에 두개가 생성되어 ptr1, ptr2 이 저장한 값을 넘겨준 것이기 때문이다. 내부에서 직접적으로 저장된 값의 변화 없이 *x = 1; 로 선언하게 되면 a의 값은 변경된다. 하지만 x 가 저장한 주소를 변경시킨다고해서 ptr1 이 저장한 주소값이 변하는 것은 아니다.
1 2 3 4 5 6 7 | void func(int A, int B, int *x, int *y){ A = B + 100; *x = B + 200; B++; y = y + 100; printf("<func> (A) %d (B) %d (*x) %d (*y) %d \n", A, B, *x, *y ); } | cs |
func함수가 호출되면서 변수 A 의 값으로 60, 변수 B는 11, 포인터의 주소로 x = ptr1 = &a, y = ptr2 = &b ; 를 받은 것이다.
A 값은 B+100 하여 111;
*x의 값은 B + 200 하여 211; 즉, *(&a) = 211 ; 이므로 메인함수의 변수 a의 값이 211 이 된다.
B++; 는 12의 값을 갖는다.
y는 y+100; 주소를 100*(4) 칸 이동한다.
출력은 <func> 111, 12, 211 , ???
마지막 y는 어디로 이동한 것인지 모르기때문에 쓰레기값 혹은 어떤 값이 나올 지 모른다.
이후 메인함수로 복귀하여,
<3> 은 a 값의 변화만 있으므로
211, 11 ,211 ,11 을 출력하게 된다.
'2016 > C_tutoring' 카테고리의 다른 글
[C]포인터 (0) | 2017.07.22 |
---|