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;
  *= 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;
  *= 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;
  *= 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

+ Recent posts