static의 특징
main.c
#include <stdio.h>

void test(void);

int iNumC;

int main()
{
  static int iNumA=5;

  printf("main Address iNumA : %d\n", iNumA);
  printf("main Value iNumA : %08X\n"&iNumA);
  printf("main Address iNumC : %d\n", iNumC);
  printf("main Value iNumC : %08X\n"&iNumC);
  ++iNumC;
  test();
  //test();
  //test();
  printf("main Address iNumC : %d\n", iNumC);
  printf("main Value iNumC : %08X\n"&iNumC);
  return 0;
}
test.c
int iNumC;

void test(void)
{
  static int iNumA;
  int iNumB;
  
  printf("============ TEST() START =============\n");
  printf("func's TESTA(%d)\n", iNumA);
  printf("test Address iNumA : %08X (static)\n"&iNumA);  // static 변수 
  printf("test Address iNumB : %08X (지역)\n"&iNumB);  // 지역 변수 
  printf("test Address iNumC : %08X (전역)\n"&iNumC);  // 전역 변수 
  printf("=======================================\n");
  printf("test Value iNumA : %d (static)\n", iNumA);  // static 변수 
  printf("test Value iNumB : %d (지역)\n", iNumB);  // 지역 변수 
  iNumC=5;
  printf("test Value iNumC : %d (전역)\n", iNumC);  // 전역 변수 
  printf("=======================================\n");
  iNumA++;
  iNumB++;
  return;
}


위의 소스를 보면 우선 실험을 위해 main함수와 test함수를 분리해 놨다. 우선 A변수는 main과 test함수에서 static을 선언하였고 C변수는 전역변수로 선언해 놓았다. 그리고 B변수는 지역변수이다. 지역변수는 이미 알고있듯이 함수 내에서 선언할경우 지역변수가 되는데 지역변수는 알고있으므로 패스한다. 다음 전역변수부터 보도록 한다. 전역변수 C의 주소를 보면 main함수의 주소와 비슷한것을 볼수있다. 전역변수의 경우는 지역변수와 같이 스택에 저장되는 것이 아니라 BSS, DATA영역을 할당받는데 초기화를 하지 않을경우는 BSS영역에서 타입형만큼의 크기를 0으로 가득채워놓고 정보를 기억하고 있다가 초기화가 이루어지면 DATA영역에 할당되어 그 값을 기억한다. 위에 소스를 보면 main.c와 test.c에 각각 전역변수로 C를 선언되어있다. main.c에서 전역변수를 선언안하고 컴파일할경우 에러메시지와 함께 컴파일이 되지는 않지만 main.c에서도 전역변수를 선언해주면 이상없이 컴파일이 된다. 그리고 출력결과를 확인해보면 main의 전역변수 주소와 test의 전역변수 주소가 같은것을 볼수있다. 그리고 main에서 C변수를 수정하니 test의 변수도 같이 변한것을 볼수있고 test에서 5를 대입해주니 main에서도 5가 대입된것을 볼수있다. 이것을 보면 전역변수C는 모든 함수의 공유를 한다는 것을 유추할수 있는데 이것이 전역변수의 장점이자 단점이 된다. C프로그램에서 유일하게 접근성을 갖고있다. 그리고 static변수를 다시 확인해보자.
위에 출력결과를 보면 static변수A의 주소는 main과 test에서 각각 다른것을 확인할수 있다. 지역변수의 경우 함수를 빠져나가면 그값이 사라지는데 반해 static변수의 경우 함수를 호출하고 빠져나가도 그 값이 전역변수처럼 사라지지않는다. 그리고 전역변수처럼 다른함수의 접근을 허용하지 않아 보안기능을 갖고있다. 위에 소스에서는 main함수에서 A변수의 값을 5넣었다. 출력결과를보면 main은 5인데 test함수의 A변수는 0인것을 보면 쉽게 이해할수 있을 것이다.

ls -al >test.A  <<-- 화면에 보여줄 파일을 test.A로 저장해준다.(reDirection)
#include <stdio.h>

int main()
{

  fprintf(stdout,"STDOUT \n");  // 표준출력 
  fprintf(stderr,"STDERR \n");  // 표준출력 
  return 0;
}
표준 입출력장치 파일 핸들 값.
stdin   0
stdout 1
stderr  2
malloc()함수
malloc()함수는 heap영역에 메모리를 할당한다. 메모리의 부족으로 할당에 실패하면 NULL을 반환. 
프로그램의 실행이 끝나기 전에 반드시 free()함수를 호출하여 할당을 해제해 주어야한다. 만약 해제하지 않으면
메모리에 그대로 남아있어 계속 쌓이다 보면 결국 메모리의 용량이 부족하게 되는 현상이 나타난다. 
#include <stdio.h>
#include <stdlib.h>    // malloc() 함수 사용 
#include <string.h>    // strcpy() 함수 사용 

typedef struct tag_student
{
  char name[20];
  int score;
} student;

int main()
{
  student st[3];
  student *sp;
  int i;

  sp=(student*)malloc(sizeof(student));
  if(sp==NULL)  
  {  // 메모리 할당 실패할 경우 
    printf("allocation error\n");
    exit(-1);  // 프로그램을 종료 (return(main함수를 종료)을 추천)
  }
  
  i=0;  // 초기화는 반복문 앞에 써주는 것이 좋다.
  while(i<3)
  {
    printf("Please enter student name & score : ");
    scanf("%s %d", sp->name, &sp->score);
    //strcpy(st[i].name, sp->name);  // 배열에 복사 
    //st[i++].score=sp->score;
    st[i++]=*sp;  // 위와 같다.
  }
  free(sp);

  for(i=0; i<3; i++)
  {
    printf("student name : %s,\tscore : %d\n", st[i].name, st[i].score);
  }
  return 0;
}







정적 연결리스트 (static linked list)
#include <stdio.h>

typedef struct test
{
  int iNum;
  struct test *Next;
}TEST;

int main()
{
  TEST A1={1, };
  TEST A2={2, };
  TEST A3={3, };
  TEST A4={4, };
  TEST A5={5, };
  TEST A6={6, };
  TEST *p;
  
  p = &A1;
//  A1.Next = &A2;  p->&A1과 같다
  p->Next=&A2;
  A2.Next=&A3;
  A3.Next=&A4;
  A4.Next=&A5;
  A5.Next=&A6;
  
  printf("A1.iNum : %d\n", p->iNum);
  printf("A2.iNum : %d\n", A1.Next->iNum);
  printf("A3.iNum : %d\n", A2.Next->iNum);
  printf("A4.iNum : %d\n", A3.Next->iNum);
  printf("A5.iNum : %d\n", A4.Next->iNum);
  printf("A5.iNum : %d\n\n", A5.Next->iNum);
  
  printf("A1.iNum : %d\n", p->iNum);
  printf("A2.iNum : %d\n", p->Next->iNum);
  printf("A3.iNum : %d\n", p->Next->Next->iNum);
  printf("A4.iNum : %d\n", p->Next->Next->Next->iNum);
  printf("A5.iNum : %d\n", p->Next->Next->Next->Next->iNum);
  printf("A6.iNum : %d\n\n", p->Next->Next->Next->Next->Next->iNum);
  
  return 0;
}
위의 소스에서   A3.Next=&A4; 을 주석처리해서 삭제할경우 결과가 어떻게 나오는지 확인해보자
위의 소소에 printf를 너무 난발해서 보기가 싫다면 아래와 같이 고쳐서 실행해 보자.
#define 
\test 1 ☜ test 앞에 역슬러시(\)를 붙일경우 #define 하고 연결이 되서 #define test 1 하고 똑같이 취급된다.
역슬러시(\)를 안붙일경우는 #define 따로 test 1 따로 이므로 문법에 맞지 안다.
구조체 사용자 정의 (struct)

 위의 그림의 3가지 문법 모두 동일하다. 첫번째 문법은 구조체를 선언할때마다 struct을 붙여 줘야하지만 두번째 세번째 문법에서는 struct을 쓰지 않는 것을 볼수 있을 것이다. 
구조체의 초기화
#include <stdio.h>

typedef struct _memset
{
int iAddr;
char cChara;
int iSize;
}MEMSET;

void my_memset(void *, unsigned char, int);

void printmem(MEMSET *);

int main()
{
MEMSET A = {0, };
my_memset(&A,0,sizeof(A));
printmem(&A);
return 0;
}

void printmem(MEMSET *stData)
{
printf("A.iAddress : %d\n",stData->iAddr);
printf("A.cChara   : %d\n",stData->cChara);
printf("A.iSize    : %d\n",stData->iSize);
return;
}

void my_memset(void *Addr, unsigned char ucChara, int iSize)
{
while(iSize>0)
{
--iSize;
*((unsigned char *)Addr+iSize) = ucChara;
}
return;
}
위의 소스에서 MEMSET A = {0, }; 을 해주면 A구조체 안의 변수 iAddr, cChara, iSize가 모두 0으로 초기화가 된다. 마찮가지로 my_memset함수를 호출하여도 A의 구조체의 변수가 모두 초기화 되는 것을 볼수 있을 것이다.
 참고) void * 형은 어떠한 형태로든 초기화 할수 있기 때문에 int나 char처럼 크기가 정해져 있지 않다. 때문에 반드시 캐스팅을 해서 타입형을 맞춰주어야한다. 
string.h 파일안에 bzero와 memset 이있어 굳이 저렇게 만들어 쓰지 않아도 됨. 저렇다는걸 알아보기위함.


+ Recent posts