如何在运行时在 C 中增加指针或数组(在编译时不知道结束长度)

How to grow a pointer or an array in C at runtime (without knowing the end length at compile time)

提问人:ecjb 提问时间:2/22/2023 最后编辑:Chrisecjb 更新时间:2/22/2023 访问量:104

问:

我想在运行时增加一个数组(无需使用 macos 预先处理长度)

我有以下问题

  1. 是否可以使用数组来做到这一点?
  2. 如果没有,我应该使用指向 int 的指针吗?

我尝试了以下代码(并期望作为输出)但得到012000

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

int main()
{
    int *arr = NULL; 
    size_t n = 0; 
    for (int i = 0; i < 3; ++i) { 
        arr = realloc(arr, (n + 1) * sizeof *arr); 
        arr[n++] = i; 
        printf("%d", *arr);
    } 
}
数组 c 指针 malloc realloc

评论

3赞 Craig Estey 2/22/2023
你的代码很好(简单但很好)。您想要:打印当前元素而不是[总是]第一个元素。reallocprintf(" %d",arr[n - 1]);
1赞 stark 2/22/2023
*arr 是 arr 中的第一个元素
1赞 Fe2O3 2/22/2023
...或者它有助于显示参考,而不是黑匣子。(PS:感谢在没有典型第一的情况下使用。做得好!和。。。别忘了要干净...printf( "%d: %d and n = %d\n", i, arr[i], n );realloc()malloc()free():-)
3赞 Chris 2/22/2023
建议:拨打电话不是免费的。将数组增加 2 倍,而不是每次都增加 1,以最大程度地减少重新分配。realloc
1赞 yano 2/22/2023
还有一件事,您应该检查 的返回值以确保它成功,然后再尝试写入它给你的内存(您目前希望)。realloc

答:

3赞 2 revschux - Reinstate Monica #1

OP大多拥有它。

它只是每次打印第一个元素。

    // printf("%d", *arr);
    printf("%d", arr[n-1]);

是否可以使用数组来做到这一点?

不。在 C 中,数组一旦被定义就无法改变大小。

但是,指针分配和引用的内存大小可能会更改。

1赞 chqrlie 2/22/2023 #2

重新分配数组的方式很好,尽管效率低下。你没有得到预期输出的原因是你输出了第一个元素 3 次。

如果您提前知道最终长度,建议一次性分配数组,在其他情况下,需要动态重新分配大型数组,建议按照几何级数使用递增的大小重新分配:

下面是一个使用黄金比例的示例:

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

int main() {
    char *arr = NULL; 
    size_t size = 0;
    size_t pos = 0;
    int c;
    while ((c = getchar()) != EOF) {
        if (pos + 1 > size) {
            // increase size by a ratio of 1.625
            // with an offset to handle the initial case without a test
            size_t new_size = size + (size >> 1) + (size >> 3) + 32;
            char *new_arr = realloc(arr, sizeof(*arr) * new_size);
            if (new_arr == NULL) {
                fprintf(stderr, "cannot reallocate array for %zu bytes\n", new_size);
                free(arr);
                return 1;
            }
            arr = new_arr;
            size = new_size;
        }
        arr[pos++] = c;
    }
    if (arr == NULL) {
        fprintf(stderr, "empty file\n");
        return 1;
    }
    arr[pos] = '\0';
    char *new_arr = realloc(arr, sizeof(*arr) * (pos + 1));
    if (new_arr != NULL) {
        arr = new_arr;
        size = pos + 1;
    }
    /* more code to handle full buffer */
    free(arr);
    return 0;
}

评论

0赞 Erdal Küçük 2/22/2023
size + (size >> 1) + (size >> 3)这太奇特了,我感觉像找到了一枚金币。只是出于好奇,为什么这个数字.只是武断?看起来没有任何后来的影响(忽略事实,如果 )。32size == 0
0赞 chqrlie 2/22/2023
@ErdalKüçük:正确,只是一个简单的偏移量来处理没有分支的初始情况。+ 32