C : Realloc 不适用于动态双指针数组

C : Realloc doesn't work with dynamic double pointer array

我遇到了一些关于使用双指针动态数组重新分配的问题。 我想要执行的是 add 2 pointers of type Flight* inside the array schedule of 类型航班 **.

为此,我依赖 Functions.c 文件中的函数 add_flight。 此函数要求用户提供航空公司和航班号值,并将这些数据存储在新的 Flight* f 中。如果计划是 null(尚未添加航班),它会 为新创建的航班分配 内存,否则它会 realloc 计划的大小,以便添加新航班。

Main.c 文件:

int main() {
    int choice = 1;
    Flight** schedule = NULL;   

    printf("---AIRPORT MANAGER---");
    schedule = add_flight(schedule);
    printf("\n%s : %d\n", (*schedule)->airline, (*schedule)->flightNumber);
    schedule = add_flight(schedule);
    printf("\n%s : %d\n", (*schedule + 1)->airline, (*schedule)->flightNumber);

    return 0;
}

Functions.c 文件:

#include "Functions.h"

void mygets(char* s, int maxLength) {
    fflush(stdout);
    if (fgets(s, maxLength, stdin) != NULL) {
        size_t lastIndex = strlen(s) - 1;
        if (s[lastIndex] == '\n')
            s[lastIndex] = '[=11=]';
    }
}

void flush() {
    char buffer;
    while ((buffer = getchar()) != EOF && buffer != '\n');
}

Flight** add_flight(Flight** schedule) {
    Flight* f;
    char buffer[100];

    if ((f = (Flight*)malloc(sizeof(Flight*))) == NULL) {
        exit(1);
    }

    printf("\n\n---FLIGHT CREATION---");
    printf("\nAirline: ");
    mygets(buffer, sizeof(buffer));
    if ((f->airline = _strdup(buffer)) == NULL) {
        exit(1);
    }
    memset(buffer, 0, 100);

    printf("\nFlight number: ");
    scanf("%d", &f->flightNumber);
    flush();

    if (schedule == NULL) {
        if ((schedule = malloc(sizeof(Flight*))) == NULL) {
            exit(1);
        }       
        *schedule = f;
    }
    else {
        int numberFlights = ((sizeof(*schedule)) / 4) + 1;
        if ((schedule = realloc(schedule, numberFlights * sizeof(Flight*))) == NULL) {
            exit(1);
        }
        *(schedule + numberFlights -1) = f;
    }

    return schedule;
}

在 main.c

中执行第二次调用 add_flight 时出现问题

add_flight函数中,数据确实存储在新的Flight* f中,然后考虑else语句:变量numberFlights获取值2。但是, realloc 不起作用,时间表没有扩大,因此仍然只有第一个航班存储在这个时间表数组中。我不明白为什么第二个航班没有添加到时间表中。

谁能解释一下为什么这个 realloc 失败了? 感谢您的帮助:)

sizeof 运算符在编译时求值。它不能用于确定动态分配数组的大小。

C 将跟踪数组实际大小的负担强加给程序员。您可以保留一个单独的计数变量,但由于实际数组及其大小属于一起,因此将它们并排存储在一个结构中很有用:

typedef struct Flight Flight;
typedef struct Flights Flights;

struct Flight {
    char airline[4];
    int number;
    char dest[4];
};

struct Flights {
    Flight *flight;
    int count;
};

不对数组进行操作,而是对结构进行操作:

void add_flight(Flights *fl,
    const char *airline, int number, const char *dest)
{
    int n = fl->count++;        // n is old count; fl->count is new count

    fl->flight = realloc(fl->flight,
        (fl->count + 1) * sizeof(*fl->flight));

    snprintf(fl->flight[n].airline, 4, "%s", airline);
    snprintf(fl->flight[n].dest, 4, "%s", dest);
    fl->flight[n].number = number;
}

使用 NULL 和零计数初始化航班结构,完成后不要忘记释放已用内存:

int main(void)
{
    Flights fl = {NULL, 0};

    add_flight(&fl, "AF", 5512, "CDG");
    add_flight(&fl, "AA", 1100, "ATL");
    add_flight(&fl, "LH", 6537, "FRA");
    add_flight(&fl, "BA", 8821, "LHR");
    add_flight(&fl, "IB", 1081, "EZE");

    print_flights(&fl);

    free(fl.flight);

    return 0;
}

您可以看到它的实际效果 here。一些观察:

  • 无需区分添加第一个航班和后续航班,因为 realloc(NULL, size) 的行为与 malloc(size).
  • 完全相同
  • 为每个添加的项目重新分配内存不是很有效。相反,您选择一个合适的初始数组大小,如 4 或 8,然后在达到限制时将大小加倍。这意味着分配的大小和计数可能不同,您需要在航班结构中添加一个 memsize 字段。
  • 以上代码依赖于手动初始化和销毁​​。通常,您会编写 "constructor" 和 "destructor" 函数来为您完成此操作。