VIPS를 쏜다는 말에 혹해서, 친구의 C언어 프로그래밍 숙제를 해주다가, 재미난걸 알아버렸다.
변수를 이용할 때, 구조체 안에 있는 특정 변수의 값만 필요하다면 .연산자를 쓰면 된다는 건 알고 있다. 구조체 포인터에서 그 안에 있는게 필요하면 ->연산자를 쓰면 된다.

그런데, 구조체를 이용해서 배열을 이용하면, 배열 각각의 요소를 처리하는건 쉽지만 배열의 순서나 배열을 중간에 추가하는 작업같은건 아주 어려운 작업이 된다. 이 작업을 자기참조구조체라는 개념을 이용하면 쉽게 해결할 수 있다.

선언은 간단하다. 구조체를 하나 선언하는데, 다음과 같이 선언하면 된다
struct mania
{
    int a;
    struct mania *next;
}
그러고나면, next라는 포인터는 mania라는 구조를 구조체를 가리키게 된다. 그럼 next는 다시 그 안에 next를 갖고 있다. 물론 이 next와 앞의 next는 내부변수이므로 서로 구별되고, 다른 주소를 가리키게 되므로 아무 문제 없다. 문제는 가장 마지막 변수에서 생기는데, 마지막 변수는 next가 없으므로 에러가 난다. 따라서, 최초에 선언할 때 next를 NULL로 초기화를 해 두면 괜찮다.

우선, 제일 처음 구조체를 선언할 때 다음과 같이 해 준다.
struct mania dummy; //임시 시작점이다.
struct mania *start=&dummy; //시작점의 주소를 start라는 포인터에 넣는다. struct mania *sequence; //실제로 우리가 사용할 포인터이다.
struct mania *work; //작업용 포인터
그럼, 이제 첫 세팅을 해보자.
start=&dmy;
start->next=NULL;
처음엔 당연히 아무것도 없으므로 NULL이다.
여기에 뭘 넣기 전에, 일단 next에 해당하는 녀석의 메모리를 확보를 해 둘 필요가 있다. 메모리의 확보는 malloc, calloc같은 함수로 한다.[각주:1]
sequence=(struct mania *)malloc(sizeof(struct mania));
이렇게 하면 sequence라는 이름의 mania구조를 가진 포인터에 sizeof(struct mania)만큼의 크기를 가진 메모리가 할당된다. 그런데, 이건 딱 한개만 확보하는 것이므로 체인의 고리를 만들어 나갈 때는 만들 때마다 메모리를 할당해야 한다. 이 점에 주의해서 문제를 잘 해결해 보기 바란다.

아무튼, 이걸 이용하는 개념은 다음과 같다.
제일 처음에 start포인터를 사용한다. [각주:2]
start->next는 start포인터 뒤에 있는 녀석이다.
물론 start->next->next는 start포인터의 뒤에뒤에 있는 녀석이다.
sequence는 체인의 가장 끝에 있는 녀석이다.
이제, next의 포인터를 적당히 지정해주기만 하면 체인을 이리저리 연결할 수 있다.
가령, 두번째 체인을 세번째 체인과 바꾸고 싶다면?
적당한 mania구조를 가진 temp를 지정하고
struct mania temp;
temp=start->next->next;
start->next->next=start->next;
start->next=temp;
이런식으로 하면 두번째와 세번째가 바뀐다.

자, 나머지는 잔머리다! (무책임 -_-;)

  1. 난 말록, 콜록, 뭐 이렇게 읽는다. calloc은 "씨-얼록"으로 읽는게 맞다는데, 뭐 알아들으면 되지 않겠는가. [본문으로]
  2. start, sequence, next등은 그냥 임의로 붙인 이름일 뿐이다! [본문으로]
by snowall 2007. 2. 27. 14:31