1

このような構造体があるとします..

struct object{
     int id;
     char *name;
     node *list_head; //a pointer to the head of a linked list
};

typedef struct object object;

構造体変数を静的に宣言しました。temp_obj以下に示すように、リストに要素を挿入する関数にこれを値で渡す必要があります。

add_elementandprint_list関数は正常に機能していると想定できます。その後リストを印刷するfunction_aと、挿入された要素は印刷されません。これは、構造体を値として渡しているため、 で行われた変更が のfunction_a前に宣言された構造体に反映されないためだと思いますfunction_a

しかし、与えられたインターフェースのために、構造体を値で渡す必要があります。この場合、元の構造に変更を反映するにはどうすればよいですか?

object temp_obj
function_a(temp_obj);
print_list(temp_obj.list_head);

void function_a(object obj){
    //add an element to the list
    int num = 1;
    add_element(&obj.list_head, num);
}
4

4 に答える 4

2

あなたはめちゃくちゃだ !

インターフェイスを変更できない場合、「値渡し」を「参照渡し」のように機能させる方法はありません。

あなたのオプションは、インターフェイスを変更して、または関数が(または)object *を返すようにすることです。これらのオプションはすべて、インターフェイスを変更する必要があります。objectobject*

于 2012-11-22T04:52:30.433 に答える
2

それほど面倒ではない条件でそれを行うことができますが、それは一種のチートです.

add_element()関数が新しい要素をリストの先頭ではなく末尾に追加する場合、およびリストに最初のノードが存在するように配置する場合は、ほぼそれを行うことができます。

証拠:

#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void err_exit(const char *fmt, ...);

typedef struct node   node;
typedef struct object object;

struct object
{
    int   id;
    char *name;
    node *list_head; //a pointer to the head of a linked list
};

struct node
{
    node   *next;
    object *data;
};

static void add_element(node **list, int value)
{
    assert(list != 0);
    object *new_objt = calloc(sizeof(object), 1);
    node   *new_node = calloc(sizeof(node),   1);
    if (new_objt == 0 || new_node == 0)
        err_exit("Out of memory in %s\n", __func__);
    node *next = *list;
    while (next->next != 0)
        next = next->next;
    next->next = new_node;
    new_node->data = new_objt;
    new_objt->id = value;
}

static void print_list(const node *list)
{
    assert(list != 0);
    node *next = list->next;
    printf("List: ");
    while (next != 0)
    {
        if (next->data != 0)
            printf("%d ", next->data->id);
        next = next->next;
    }
    printf("EOL\n");
}

static void function_a(object obj)
{
    int num = 1;
    add_element(&obj.list_head, num);
}

int main(void)
{
    node   temp_node = { 0, 0 };
    object temp_obj  = { 0, 0, &temp_node };    // Key trick!

    print_list(&temp_node);
    function_a(temp_obj);
    print_list(&temp_node);
    function_a(temp_obj);
    print_list(&temp_node);

    return 0;
}

static void err_exit(const char *fmt, ...)
{
    int errnum = errno;
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errno != 0)
        fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
    putc('\n', stderr);
    exit(EXIT_FAILURE);
}

コンパイル

gcc -O3 -g -std=c99   -Wall -Wextra node.c -o node  

出力:

List: EOL
List: 1 EOL
List: 1 1 EOL

演習の目的が脳死状態のインターフェースを打ち負かすことである場合、これはそれを回避します。演習の目的が使用可能なインターフェイスを作成することである場合は、おそらくこの方法では行いません。に構造体へのポインターを渡すとfunction_a()list_head.

于 2012-11-22T05:26:27.670 に答える
0

値渡しではできません..インターフェイスの設計を変更し、参照渡しを使用する必要があります

于 2012-11-22T04:54:24.447 に答える
0

list_headはポインタなので、なぜこれを行うのですか:

add_element(&obj.list_head, num);

これは正しい方法です:

add_element(obj.list_head, num);

リストの先頭は、その最初の要素です。それは決して変わらないので、渡す必要はありません&obj.list_head。リスト ヘッドのアドレスを保持するポインタのアドレスではなく、リスト ヘッドのアドレスのみが必要です。

「node」構造体に「next」メンバーがあると仮定すると、add_element() の実装は次のようになります。

void add_element(node* head, int num)
{
    /* Iterate over the list that starts at 'head' and when we reach the end,
       insert 'num' as a new element */
    node* cur = head;
    while (cur->next != NULL)
        cur = cur->next;
    /* We're at the end. */
    cur->next = malloc(sizeof(node));
    cur->next->next = NULL;
    cur->next->num = num;
}

object構造体にはポインター メンバーがあるため、値渡しは正しく機能します。つまり、変数のコピーobjectはすべて浅いコピーであるため、変数のコピーは引き続き同じデータを指します (同じデータがすべてのコピーで共有されます)。

于 2012-11-22T05:01:36.580 に答える