C

포인터

룸훼훼 2010. 8. 6. 12:12
반응형

(동규글펌)

포인터

 

#include <stdio.h>
int main()
{
  int a= 100;          // int형 변수 a 를 100으로 초기화
  int *p;            // int형 포인터변수 p 선언
  p=&a;              // 포인터변수 p에 a의 주소값 대입
  *p=0x99;            // *연산자를 통해 포인터변수 p가 참조하고 있는 주소의 값을 16진수 99로 초기화
  *((int*)(0x22ff54))=0x77;    // *연산자를 통해 0x22ff54 번지를 int형 포인터 타입으로 선언과 동시에 16진수
                // 77로 초기화
  printf("%x\n",a);        // a의 값을 16진수로 출력
  printf("%x\n",p);        // p의 값을 16진수로 출력
  printf("%x\n",&a);      // a의 주소값을 16진수로 출력
  printf("%x\n",&p);      // p의 주소값을 16진수로 출력


  return 0;            // 정상종료를 의미
}

결과:
77
22ff54
22ff54
22ff50

오늘 수업시간에 한 코드 입니다.
기본적인 설명은 주석을 보시면 아실테고 int형 포인터 변수 p를 선언. 포인터 변수 p는 주소만을 받아 들입니다. 
예를 들어 int *p=55; 라고 선언하게 되면 메모리주소 55가 p가 됩니다. 우리는 지금 포인터 변수 p에 a의 주소값을 대입했습니다.
지금 a의 주소가 22FF54 이므로 p는 22FF54 를 가지게 됩니다. *p 는 *연산자를 통해 p가 가지고 있는 주소값으로 가서 그
주소가 가지고 있는 값이 됩니다. 여기서는 a의 값이 됩니다. CM님이 말씀하셨듯이 int *p; 에서의 * 과 *p=0x99 에서의 * 은
틀린 것입니다. int* p; 는 int형 포인터 변수를 선언한다는 뜻이고, *p 는 포인터 변수 p가 참조하고 있는 주소의 값을 말하는
연산자 입니다. (CM 님 말씀따라 따라가기 연산자 입니다.)




 

아래 코드는 동준이랑 혜정이가 궁금해서 하던 코드가 있었는데 정확하게는 생각 안나서 비슷하게 제가 짠건데요.
 

#include <stdio.h>

int main()
{
  int a=300;
  char b = (char)a;
  int *p;
  p=&a;
  *((int*)(0x12ff78))=0x88;


  printf("a의 값: %x\n",a);
  printf("b의 값: %d\n",b);
  printf("a의 주소값: 0x%x\n",&a);
  printf("p가 가지고 있는 값: %x\n",p);
  printf("p의 주소값: 0x%x\n",&p);
  printf("\n");
  printf("0x12ff7f의 값: %x\n",*((int*)(0x12ff7f)));
  printf("0x12ff7e의 값: %x\n",*((int*)(0x12ff7e)));
  printf("0x12ff7d의 값: %x\n",*((int*)(0x12ff7d)));
  printf("0x12ff7c의 값: %x\n",*((int*)(0x12ff7c)));
  printf("0x12ff7b의 값: %x\n",*((int*)(0x12ff7b)));
  printf("0x12ff7a의 값: %x\n",*((int*)(0x12ff7a)));
  printf("0x12ff79의 값: %x\n",*((int*)(0x12ff79)));
  printf("0x12ff78의 값: %x\n",*((int*)(0x12ff78)));
  printf("0x12ff77의 값: %x\n",*((int*)(0x12ff77)));
  printf("0x12ff76의 값: %x\n",*((int*)(0x12ff76)));
  printf("0x12ff75의 값: %x\n",*((int*)(0x12ff75)));
  printf("\n");
  
  *((int*)(0x12ff77))=0x77;
  printf("0x12ff77에 0x77을 대입하고 난 후의 결과\n");
  printf("a의 값: %x\n",a);
  printf("0x12ff7f의 값: %x\n",*((int*)(0x12ff7f)));
  printf("0x12ff7e의 값: %x\n",*((int*)(0x12ff7e)));
  printf("0x12ff7d의 값: %x\n",*((int*)(0x12ff7d)));  
  printf("0x12ff7c의 값: %x\n",*((int*)(0x12ff7c)));
  printf("0x12ff7b의 값: %x\n",*((int*)(0x12ff7b)));
  printf("0x12ff7a의 값: %x\n",*((int*)(0x12ff7a)));
  printf("0x12ff79의 값: %x\n",*((int*)(0x12ff79)));
  printf("0x12ff78의 값: %x\n",*((int*)(0x12ff78)));
  printf("0x12ff77의 값: %x\n",*((int*)(0x12ff77)));
  printf("0x12ff76의 값: %x\n",*((int*)(0x12ff76)));
  printf("0x12ff75의 값: %x\n",*((int*)(0x12ff75)));
  printf("0x12ff74의 값: %x\n",*((int*)(0x12ff74)));

  return 0;
}



우선 b의 값이 44가 나온 것을 설명 드리면 int 형 a 변수가 300으로 초기화 되었습니다. 그런데 여기서 char형 변수 b에 int형 변수 a 를 char 형으로 형변환시킨 다음에 저장을 했습니다. 그래서 b의 결과는 44가 나왔습니다. 먼저 300을 2진수로 표현해보죠.
0000 0000 0000 0000 0000 0001 0101 1000 이네요. int 형이기때문에 4byte 공간을 사용하겠죠. 이제 char 형으로 형변환 시킵니다. 사실 변환이라는 말이 들어가서 그렇지 1byte 만 읽어 오는 것입니다. 어디서 부터? 뒤에서부터 읽어 옵니다. 뒤에서부터
1byte면 0101 1000 이네요. 0001 부분이 잘려나가게 됩니다. 그래서 44라는 결과가 나오게 됩니다.


위 코드의 실행 결과를 표로 만들면 이렇게 됩니다. ( 0x12FF77에 77을 대입하기 전까지 )



예를 들면 printf("0x12ff7f의 값: %x\n",*((int*)(0x12ff7f))); 는 0x12ff7f 부터 4byte(32bit)를 읽어오라는 말입니다. 표를 통해 보면 쉽게 이해가 가실거라고 생각합니다. 모르시면 따로 말씀하시면 설명 해드리겠습니다.


마지막으로 *((int*)(0x12ff77)) 에 0x77을 대입하면 77번지의 상위 1byte로 77이라는 숫자가 표현 가능하게 때문에 상위 1byte에 77 (0111 0111) 을 넣고 나머지 3byte 는 0 ( 0000 0000 0000 0000 0000 0000 ) 으로 초기화 합니다. 78번지가 0이 된 이유는 77 의 0 부분부터 읽어 오기 때문입니다. 표를 하나 더 그려 드리고 싶지만 지금 시간이........ㅠ_ ㅠ
위의 표만 이해하시면 마지막 설명도 쉽게 이해 되실거라 생각합니다.

그리고 공부하다가 포인터 변수가 왜 4Byte 인지 궁금하신 분들이 계실거라고 생각해서 제가 알고 있는게 맞나 싶어서 찾아봤는데 아닐수도 있다는 의견이 있어서 확실하다고는 말씀 못드리겠습니다.

포인터 변수는 double 형이든 char 형이든 int 형이든 무조건 4byte 를 가집니다. 제가 알기로는 메모리의 주소 체계가 4byte 라서 그런 줄 알고 있습니다. 위 표에서도 볼 수 있듯이 주소 체계가 4byte 입니다. 하지만 이것이 정답이라고 확답은 못 드리겠네요. 이 부분은 CM님에게 넘기는게 나을듯 합니다. 궁금하신 분은 http://kldp.org/node/39915 이쪽으로!

포인터 변수에 타입이 있다고 했는데 같은 크기는 모두 4byte 인데 double, int, char 같은 타입이 있는 이유는 포인터 변수가 char 형인데 참조하고 있는 주소의 값이 int 형이라면 int형의 값을 char형의 크기만큼만 읽어 오게 됩니다. 즉, int형 변수 100이 있고 이를 참조하는 char *pa 가 있다면 위에 나왔던 코드처럼 1byte만 읽어와서 44라는 엉뚱한 값이 되게 됩니다.  포인터 변수 앞에 자료형은 메모리를 참조하는 방법이라고 생각하시면 될듯 합니다.

적어 놓고 나니 쓸데없는 내용도 많고 나중에 배우게 될 내용들이 대부분이네요. 모르셔도 되는 내용들이 많으니까 이해 안되시더라도 너무 신경 안쓰셔도 될거예요. CM님이 다 가르쳐 주실 부분들이니까요. 저보다 잘 알고 계시거나 제가 잘못 설명한 부분이 있으면 꼭!! 말씀해주세요.


P.s : 팀블로그 잘 꾸미실분 관리자 드립니다. 동준아 ATmega 코드도 좀 올려주라! 될 수 있으면 비트 연산자 쓴거 말고 우리가 수업중에 배운 것들로만 해서~

반응형

'C' 카테고리의 다른 글

===== 웹 컴파일러 ======  (0) 2010.09.28
함수 -  (0) 2010.08.06
배열  (0) 2010.06.18
코딩 및 컴파일 과정  (0) 2010.05.12
C언어 역사  (0) 2010.05.12