在C语言中调整数组大小

7

假设我这样分配了一个数组:

char* array[]={"This"};

然后我想给数组[ ]分配一个新值,以便它存储"This"和"That",有没有办法改变数组的大小,以便它可以容纳新的值?


2
请注意,您在此处声明了一个二维数组。我不确定这是否是您的意图? - harald
1
@harald:这不是一个二维数组(也许在你发表评论后但编辑窗口关闭前问题被更改了)。 - Steve Jessop
1
@SteveJessop,从技术上讲,你是正确的。它是一个指向字符的指针数组,但它被初始化为一个指向字符串的指针数组(只有一个元素)。也许这就是他想要的,但从问题中不太清楚。 - harald
3
@harald: 我认为这是他想要的(除了数组变量不能做到他想要的)。他开始使用一个指向“ This ”的指针数组,后来他想要一个包含两个指针的数组(一个指向“This”,另一个指向“That”)。 - Steve Jessop
@SteveJessop,看起来你是对的 :) - harald
4个回答

17

不,你不能改变数组的大小。你可以使用动态分配的 char* 列表,根据需要使用 realloc()

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

int main()
{
    char** array = malloc(1 * sizeof(*array));

    if (array)
    {
        array[0] = "This";

        printf("%s\n------\n", array[0]);

        char** tmp = realloc(array, 2 * sizeof(*array));
        if (tmp)
        {
            array = tmp;
            array[1] = "That";

            printf("%s\n", array[0]);
            printf("%s\n", array[1]);
        }

        free(array);
    }
    return 0;
}

查看在线演示:https://ideone.com/ng00k


你可以使用VLA,但是即使数组的大小可以在运行时变化,一旦数组被创建,就不能改变其大小(直到它被销毁并重新创建)。 - Jonathan Leffler
我运行了这个程序,它可以工作,但我不太明白。一个字符串可以有多长?看起来malloc正在为'array'指针分配大小,当我使用这段代码时,在我的系统上是8个字节。然后我增加了分配给array [0]的字符串长度到60个字符,通过valgrind运行程序,没有报告任何问题。我不明白。 - Andy Alt
你不需要释放初始的malloc吗? - Miguel Tomás

3

无法调整数组大小。您可以简单地创建一个大小为2的新数组,然后将所有数据从先前的数组复制到新数组中。使用动态内存的realloc可以为您完成此操作。更好的方法是使用数据结构,例如LinkedListsVectors,您可以在网上找到更多信息。


2
在我看来,添加一个具体的代码示例会很有帮助。 - shevy

2

你无法调整数组对象的大小。

你需要动态分配array的内存,并使用realloc进行扩展。例如:

size_t current_size = 0;

char **array = malloc((current_size + 1) * sizeof *array);
if (array)
{
  array[current_size++] = "This";
}
...
/**
 * If realloc cannot extend the buffer, it will return NULL and leave
 * the original buffer intact; however, if we assign NULL back to array,
 * we lose our handle to the original buffer, causing a memory leak, so
 * we assign the result to a temporary variable.
 */
char **tmp = realloc(array, (current_size + 1) * sizeof *array)
if (tmp)
{
  array = tmp;
  array[current_size++] = "That";
}
else
{
  // realloc failed to extend the buffer; original buffer
  // is left intact.
}

注意事项:

realloc 是一个相对昂贵的调用,因此你(通常)不希望像这里一样每次只扩展一个元素。更常见的策略是选择一个初始大小,涵盖大多数情况,如果需要扩展缓冲区,则将其大小加倍。

您可以将resize操作抽象为单独的函数,像这样:

int addItem(char ***arr, char *newElement, size_t *count, size_t *bufSize)
{
  if (*count == *bufSize)
  {
     // we've run out of room; extend the buffer
     char **tmp = realloc(**arr, 2 * *bufSize * sizeof **arr);
     if (tmp)
     {
       *arr = tmp;
       *bufSize *= 2;
     }
     else
     {
       // could not extend the buffer; return failure code
       return 0;
     }
  }
  (*arr)[(*count)++] = newElement;
}

并将其称为

#define N ... // initial array size

char **array = malloc(N * sizeof *array);
size_t bufSize = N;
size_t count = 0;
...
if (addItem(&array, "This", &count, &bufSize))
  printf("# elements = %zu, buffer size = %zu\n", count, bufSize);

if (addItem(&array, "That", &count, &bufSize))
  printf("# elements = %zu, buffer size = %zu\n", count, bufSize);

以下内容均未经测试,仅为个人想法,不提供任何明示或暗示的保证。但应该足以指引您朝着正确的方向前进。


0
这是不可能的。但你可以分配一个 char* 数组:
char **array = calloc(2, sizeof(char *));
array[0] = "This";
array[1] = "That";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接