2010년/3월

3월31일 연결리스트, 전역변수

뽀얀햄스터 2010. 3. 31. 10:09

-연결리스트-
연결리스트는 구조체를 이용하여 만든다.  연결  리스트는 구조체 내에 다른 구조체를  가르키는 포인터를 멤버로  가짐으로서 만들수 있다.
#include<stdio.h>
struct
  data
{
  int  iItem;
  struct data *next;

};
int main()
{
  struct  data D1;
  struct  data D2;
  struct  data D3;
  struct data *p;
  D1.iItem=10;
  D2.iItem=20;
  D3.iItem=30;
  D1.next=&D2;
  D2.next=&D3;
  D3.next=0;
  printf("%d\n",D1.iItem);
  printf("%d\n",D1.next->iItem);
  printf("%d\n",D1.next->next->iItem);
  for(p=&D1;0!=p;p=p->next)
  {
    printf("[%d]->",p->iItem);
    
  }
  putchar('\n');
  return 0;
}

struct data *next를 통해서  다른구조체를 연결할수있다.~!
for(p=&D1;0!=p;p=p->next)
  {
    printf("[%d]->",p->iItem);
    
  }
이미 p에 D1의 주소값이 들어간다.



그리고 printf를 통해  p->iItem이니깐  D1의 iItem값이 출력되고 for이  한번 돈다.


p=p->next를 통해 D1의 next값을 따라가게되면 D2의 주소값이 p에 들어간다.
그리고 printf  출력하면 20이 출력된다.


그리고 아직 P!=0이기때문에 p=p->next 현재 D2의 주소값이 들어간후 다음 Next는 D3의 주소이기때문에 D3주소값이 들어가고 출력으로 D3의iItem을 출력한다.


그리고  p=p->next  으로  D3의 next값이  0이므로  for문을 빠져나오게 된다.


동적할당~!
void *는 모든 포인터의타입의주소를 저장할수있다. 그래서 void *는 그냥  포인터라고 생각하는게 편하다. 하지만 void *는 주소로 접근이 가능하지만...  값을 넣을수가 없다~! 만약 void *에  값을 넣을려면 넣을값의 형태를 따라  캐스팅을 해줘야한다. ~! *((int *)vp)=100;


전역 변수는 두가지로 나뉜다.. 초기화된 전역변수와 초기화 안된 전역변수로 나타낸다.
#include<stdio.h>
void
 test();
int k;
int  j;
int main()
{
  
  printf("%d\n",k);  
  k=10;
  printf("%d\n",k);
  test();
  printf("%d\n",k);
  printf("%p\n",&k);
  printf("%p\n",&j);


  return 0;
}
void  test()
{
  
  k=20;
  
}
여기서 보면 k와j가 main위에서 선언이 되었다. 그리고 초기화안된  저 값은  


메모리영역에  BSS에 들어가있다. k와 j는 전역변수로 선언이 되면 사용할시에 안에 초기값으로 0이 되어 있다.

하지만 j=0이라는 값을 전역변수로 지정하면

004068D0으로 가게 된다. 즉  주소값은 data영역의 주소가 된다. 이렇게 전역변수에 초기화0을 넣으면 data영역에 고유로  저장된다. 이렇게  전역변수를 지정하면 test()에서  선언을  안해도 사용할수 있고  값이 또 변하게 된다.~!

전역변수는 분활컴파일시  충돌이  일어날수있다. 그래서 헤더파일에..전역변수를 선언하게 되면  가져가는 main()와 다른 함수로 인해  충돌이 일어날수있다. 이럴경우 헤더파일에 extern int k(외부에 K를선언한다.K가 있다는 존재하에)를 선언하고 종속적인 함수에 다시 int k를 선언하면 사용할수있다. 그리고 분활컴파일시 각각 함수의 변수에 주소가있다 그래서 이함수안 변수끼리 주소가 같을수가 있다. 그래서 분활컴파일시 충돌이 일어날수가 있다. 그래서 LINKing에 기능중에  이 주소가 같아서 충돌을 피하게  하는  기능이 있다 이것을  주소의 재배치라고 한다.지금 우리가 사용하는 일반적인 C같은경우는 이런경우를  관대하게 넘어가지만 C++로 컴파일할경우  바로 링킹error가 나오게된다.
A.cpp 파일
#include"a.h"
int
 k;
void  test()
{  
  k=20;
}

ex.cpp 파일
#include<stdio.h>
#include"a.h"

int main()
{
  
  printf("%d\n",k);  
  k=10;
  printf("%d\n",k);
  test();
  printf("%d\n",k);
  printf("%p\n",&k);
  return 0;
}

a.h 파일

extern int k;
void test();

cl /c a.cpp
cl /c ex.cpp
cl a.obj ex.obj

실행이 된다. a.h에서 extern int ka.cpp에서 int k 때문에 실행이 가능하다 여기서  test()나 main()두함수중에 하나는 꼭 int k를 선언해야한다.~