动态添加数据到指向函数

时间:2016-01-15 17:46:21

标签: c function pointers struct pointer-to-pointer

我尝试了很多组合,但实际上没有任何效果。它已经足够长,所以我决定写这个问题。

我只想要一个指向结构的指针数组,这样我以后可以通过交换地址轻松地对它进行排序。我有一个函数从文件中获取数据并写入数组。不幸的是,我不可能在函数之外读取这些数据。

我的最后一次尝试(我删除了文件操作,因为这些不是问题):

Header.h:

#pragma once

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int32_t year;
    uint16_t month;
    uint16_t day;
} Date;

typedef struct {
    char name[16];
    Date date;
    uint32_t number;
} Player;

size_t readData(Player** players);

由source.c:

#include "Header.h"

size_t readData(Player** players) {
    players = NULL;

    players = realloc(players, sizeof(Player*) * 1);
    players[0] = malloc(sizeof(Player));
    strcpy(players[0]->name, "asd");
    printf("$ %s\n", players[0]->name);//OK

    return 1;
}

int main() {
    Player **players = NULL;
    uint32_t elemCount, i;

    elemCount = readData(players);

    printf("> %s", players[0]->name);//BUM - ERROR!

    return 0;
}

我正在使用Visual Studio Community 2015.我知道它不是用C语言进行编码,但我设法配置解决方案,它似乎不是imo。< / p>

我将非常感谢您的帮助。但是,我希望将其视为我的代码的翻版。我在StackOverFlow上尝试了一些其他问题的答案,但是他们没有帮助。

3 个答案:

答案 0 :(得分:2)

如果函数的参数不仅被读取并且也应该是输出,则必须将指向数据的指针传递给函数。如果您的数据类型为Player**,则参数类型必须为Player ***,因此可以在函数内更改itselfe的播放列表。

size_t readData(char* fname, Player*** players) {
                                // ^ players is a input and output parameter
    Player **tempPlayers = *players; // local list of players
    tempPlayers = realloc(tempPlayers, sizeof(Player*) * 1);
    tempPlayers[0] = malloc(sizeof(Player));
    strcpy(tempPlayers[0]->name, "asd");
    printf("$ %s\n", tempPlayers[0]->name);//OK

    *players = tempPlayers; // write back list of players to paramter
    return 1;
}

int main() {
    Player **players = NULL;
    uint32_t elemCount, i;

    char *fileName = NULL; 
    elemCount = readData(&players);
                      // ^

    printf("> %s", players[0]->name);//BUM - ERROR!

    return 0;
}

如果您不想使用***,可以这样做:

Player* *readData(char* fname, Player** players, size_t *size) {
    players = realloc(players, sizeof(Player*) * 1);
    players[0] = malloc(sizeof(Player));
    strcpy(players[0]->name, "asd");
    printf("$ %s\n", players[0]->name);//OK

    *size = 1;
    return players;
}

players = readData( fileName,  players, &elemCount );

答案 1 :(得分:1)

您通过 value 将指针传递给函数; players 中的原始main未更改。这与做的没什么不同:

#include <stdio.h>

void func(int x)
{
    x = 4;
}

int main()
{
    int x = 0;
    func(x);

    printf("%d\n", x);      // zero
}

我认为这些指针让你感到困惑,所以你现在应该看到你的错误。

要使修改在readData之外可见,您需要使用三个间接级别:

size_t readData(Player*** players) {
    *players = malloc(sizeof(Player*) * 1);
    *(players)[0] = malloc(sizeof(Player));
    strcpy((*players)[0]->name, "asd");
    printf("$ %s\n", (*players)[0]->name);//OK

    return 1;
}

int main() {
    Player **players = NULL;
    uint32_t elemCount, i;

    elemCount = readData(&players);

    printf("> %s", players[0]->name);  // prints 'asd'

    return 0;
}

知道传递的指针总是realloc时,使用NULL毫无意义,所以我已将其更改为malloc

并且旁注:Visual Studio非常适合C开发,并实现C99甚至C11的部分(历史上MSVC始终停留在C89)。您只需对源文件使用.c扩展名,这将使编译器假定代码为C,或者您可以在属性页中明确设置它。

答案 2 :(得分:1)

传递给readData()的

参数必须是调用者指针&#39; player&#39;的地址。

readData()到players中的每个引用都必须考虑到这一点。

呼叫者的指针&#39;播放器&#39;不会更新。

然后main()函数调用printf()尝试从地址0输出,导致未定义的行为,导致seg fault事件。

如果插入:

,则在main()函数中

printf( "player value; %p\n", (void*)players);

在当前调用printf()之前,您会看到players指针仍然包含NULL。