[혼연C] 단순연결리스트 예제 컴파일이 안돼서…

혼자 연구하는 C/C++의 단순 연결 리스트를 혹시나 싶어서 코딩해봤는데 오류를 뿜으며 컴파일이 안되더라. OSX환경이라 그런 것인지 아니면 이곳의 예제가 C++ 컴파일러여야 하는것인지, 아님 내가 그저 gcc(Apple LLVM)로 컴파일을 해서 문제가 있는 것인지는 모르겠다. 아무튼 구조체 태그를 가지고 새로운 변수를 선언/정의할 때, C에서는 일일이 struct를 붙여줘야 한다. 그냥 데이터 타입처럼 바로 쓰는 건 C++이 허용하는 문법이라고.

그래서 다시 작성함. 도대체 어디가 문제인지 좀 헤맸는데 의외로 엄청 친절하고 꼼꼼한 선생님이 계셨으니… 바로 Xcode… vi로 코딩하다 머리 뜯으며 Xcode로 옮겨보니 바로 알려주시네. 다음 코드는 오류나 경고를 모두 제거하고 표준 C로 재작성된 코드.

//  Simple Linked List
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Node {
    int value;
    struct Node *next;
};

struct Node *head;

void initList()
{
    head = (struct Node*)malloc(sizeof(struct Node));
    head->next = NULL;
}

struct Node* insertNextTo(struct Node* target, struct Node* newNode)
{
    struct Node *new;
    new = (struct Node*)malloc(sizeof(struct Node));
    *new = *newNode;

    new->next = target->next;
    target->next = new;

    //free(newNode);
    return new;
}

unsigned int removeNextTo(struct Node* target)
{
    struct Node *del;
    del = target->next;
    if(del==NULL) {
        return 0;
    }
    target->next = del->next;
    free(del);
    return 1;
}

void releaseList()
{
    while(removeNextTo(head)){;}

    free(head);
    head=NULL;
}

int main(int argc, const char *argv[])
{
    initList();

    struct Node *now, temp;

    now = head;
    int i;

    for(i=1;i<=5;i++){
        temp.value = i;
        now = insertNextTo(now, &temp);
    }

    removeNextTo(head->next);

    for(now=head->next;now;now=now->next)
    {
        printf("%02d ==>", now->value);
    }

    return 0;
}

다음과 같이 typedef를 쓰는 경우에 조금 애매한 부분이 있는데 typedef 로 구조체를 타입으로 만들 때 그 구조체가 자신을 가리키는 포인터를 멤버로 가지면, 그 때의 자신은 그냥 구조체의 포인터로 써야한다. (타입의 포인터를 쓰면 에러.)

아래와 같이 변경된다.

//  Simple Linked List
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct __node {
    int value;
    struct __node *next;
} node;

node *head;

void initList()
{
    head = (node*)malloc(sizeof(node));
    head->next = NULL;
}

node* insertNextTo(node* target, node* newNode)
{
    node *new;
    new = (node*)malloc(sizeof(node));
    *new = *newNode;

    new->next = target->next;
    target->next = new;

    //free(newNode);
    return new;
}

unsigned int removeNextTo(node* target)
{
    node *del;
    del = target->next;
    if(del==NULL) {
        return 0;
    }
    target->next = del->next;
    free(del);
    return 1;
}

void releaseList()
{
    while(removeNextTo(head)){;}

    free(head);
    head=NULL;
}

int main(int argc, const char *argv[])
{
    initList();

    node *now, temp;

    now = head;
    int i;

    for(i=1;i<=5;i++){
        temp.value = i;
        now = insertNextTo(now, &temp);
    }

    removeNextTo(head->next);

    for(now=head->next;now;now=now->next)
    {
        printf("%02d ==>", now->value);
    }

    return 0;
}

p.s. 구조체를 타입으로 선언하고 그 속에서 구조쳬 자신의 포인터를 지칭할 때는 구조체 이름과 타입 이름이 같은 것으로 간주되나, 가능하면 내부적으로 구분하여 사용하는 것이 조금 더 낫고. (왜냐하면 뒤에서 구조체 태그인지 타입명인지를 구분해야 할 때가 있으므로) 이를 구조체 내에서 명시하는 것이 좋다.