포인터, 함수의 매개변수로 전달

wtwon의 이미지

안녕하세요.
c언어를 배우는 중에 있습니다.
연결리스트로 큐를 만드는데, 선언한 구조체 포인터 변수를 함수의 매개변수로 넘겨 함수내에서 조작하려고 합니다.

head와 tail을 NULL로 초기화한 다음에 큐에 넣기 위해 addq를 합니다.
addq에서 큐가 공백이면(head==NULL) head->data에 값을 넣는 것으로 진행되는데,
5번의 인큐를 수행할 때 모두 head가 NULL로 인식되어 first node라고 출력됩니다.

원래 시나리오는 처음에만 (큐가 공백일 때) head가 NULL이어 head에 바로 newNode가 대입되게 하고
두번 째 부터는 tail과 newNode를 연결하는 것이 되어야 합니다..

분명히 제가 잘못하여 정상적인 진행이 이루어지지 않는 것 같은데
천천히 생각해보아도 왜 그런지 모르겠습니다. 잘못된 부분을 가르쳐주시면 감사하겠습니다..

#include
#include

typedef struct Node {
int data;
struct Node *next;
} Node;

void addq(struct Node *head, struct Node *tail, int data);
int deleteq(struct Node *head, struct Node *tail);

int main()
{
Node *head = (Node *)malloc(sizeof(Node));
Node *tail = (Node *)malloc(sizeof(Node));
/* init */
head = NULL;
tail = NULL;

addq(head, tail, 1);
addq(head, tail, 2);
addq(head, tail, 3);
addq(head, tail, 4);
addq(head, tail, 5);
}

void addq(struct Node *head, struct Node *tail, int data)
{
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
printf("n->d:%d, n->n:%d\n", newNode->data, newNode->next);
if(newNode == NULL)
return;
if (head == NULL) {
head = newNode;
tail = newNode;
printf("first node\n");

} else {
tail->next = newNode;
tail = newNode;
printf("not first node\n");
}

}

babbab의 이미지

void addq 에서 struct Node *head, struct Node *tail를 ** 포인터의 포인터로 바꿔 줘야 될것입니다.

struct Node *로 하면 포인터의 복사본만 패스됩니다.

wtwon의 이미지

말씀해주신 대로 해보니

queue.c: In function ‘main’:
queue.c:28:2: warning: passing argument 1 of ‘addq’ from incompatible pointer type [enabled by default]
addq(head, tail, 1);
^
queue.c:10:6: note: expected ‘struct Node **’ but argument is of type ‘struct Node *’
void addq(struct Node **head, struct Node **tail, int data);
^
queue.c:28:2: warning: passing argument 2 of ‘addq’ from incompatible pointer type [enabled by default]
addq(head, tail, 1); .. .. .. (일부 생략, 너무 길어서..)
이런 워닝이 생기고, 억지로 실행하니 segmentation fault를 뱉어냅니다..

babbab의 이미지

더 고치셔야죠.

#include <stdio.h>
 #include <stdlib.h>
 
typedef struct Node {
 int data;
 struct Node *next;
 } Node;
 
void addq(struct Node **head, struct Node **tail, int data);
 int deleteq(struct Node **head, struct Node **tail);
 void printq(struct Node *head);
 
int main()
 {
 Node *head = NULL;
 Node *tail = NULL;
 /* init */
 
addq(&head, &tail, 1);
 addq(&head, &tail, 2);
 addq(&head, &tail, 3);
 addq(&head, &tail, 4);
 addq(&head, &tail, 5);
 printq(head);
 }
 
void addq(struct Node **head, struct Node **tail, int data)
 {
 Node *newNode = (Node *)malloc(sizeof(Node));
 newNode->data = data;
 newNode->next = NULL;
 printf("n->d:%d, n->n:%p\n", newNode->data, newNode->next);
 if(newNode == NULL)
 return;
 if (*head == NULL) {
 *head = newNode;
 *tail = newNode;
 printf("first node\n");
 
} else {
 (*tail)->next = newNode;
 *tail = newNode;
 printf("not first node\n");
 }
 
}
 
void printq(struct Node *head)
{
    if (head == NULL)
        printf("Queue is Empty\n");
    else {
        while (head != NULL)
        {
            printf("%d --> ", head->data);
            head = head->next;
        }
        printf ("end\n");
    }
}

결과 출력

n->d:1, n->n:00000000
first node
n->d:2, n->n:00000000
not first node
n->d:3, n->n:00000000
not first node
n->d:4, n->n:00000000
not first node
n->d:5, n->n:00000000
not first node
1 --> 2 --> 3 --> 4 --> 5 --> end

wtwon의 이미지

더 고치긴 했습니다만, 전달하는 부분을 고치고
함수내부에서는 각각의 head랑 tail앞에 &를 붙였었는데
제가 잘못고쳤습니다.
귀한시간 내주셔서 답변해주심에 감사드립니다.

shint의 이미지

- 무조건 추가로 입력되는 노드는 tail 꼬리입니다.
- 구조체 값을 함수에서 referece 참조하는 방법을 몰라서 리턴값으로 구현해봤습니다.
- 전체 출력을 위해서. 맨 처음에 생성한 Node 주소를 head로 사용했습니다.

#include <stdio.h>
 
 
typedef struct Node 
{
    int data;
    Node *next;
} Node;
 
 
Node* addq(Node *tail, int data)
{
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
 
    //노드가 없으면 현재노드에 노드추가 
    if(tail == NULL)
    {
        tail = newNode;
        printf("%x 첫노드\n",tail);
        return tail;
    }
 
    //노드가 있으면 다음노드에 노드추가 
    tail->next = newNode;
    printf("%x\n",tail->next);
    return tail->next;
}
 
#if 0
3d2938 -> 3d2948 -> 3d2958
3d2938 -> 3d2958
#endif
 
void deleteq(Node* tail, Node* del)
{
    printf("-------------\n");
    Node * prev = NULL;
    while(1)
    {
        if(tail == NULL)
        {
            break;
        }
        printf("%x\n",tail);
        if(tail == del)
        {
            prev->next = tail->next;
        }
        prev = tail;
        tail = tail->next;
    }
}
 
#if 1
void printq(Node *tail)
{
    printf("-------------\n");
    while(1)
    {
        if(tail == NULL)
        {
            break;
        }
        printf("%x\n",tail);
        tail = tail->next;
    }
}
#endif
 
int main(int argc, char** argv) 
{
    Node *head = NULL;
    Node *tail = NULL;
    Node *del  = NULL;
 
    tail = addq(tail, 1);   head = tail;
    tail = addq(tail, 2);   del  = tail;
    tail = addq(tail, 3);
 
    deleteq(head, del);
    printq(head);
	return 0;
}
 
 
출력결과
3d2938 첫노드
3d2948
3d2958
-------------
3d2938
3d2948
3d2958
-------------
3d2938
3d2958

이와는 별도로.
이중 연결리스트 예제소스를 파일로 첨부합니다.

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

wtwon의 이미지

리턴값을 이용한 방법을 제시해 주셔서 감사합니다.
추가로.. 예제까지 첨부해주셔서 더 감사합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.