如何更改指针在 C 函数中指向的内容?

How can I change what a pointer points to within a function in C?

我正在尝试编写一个可调整大小的数组,该数组在满时会扩展。所有功能都可以使用,但调整大小功能不行。

int main(void)
{
   int arr[4];
   int *ptr = arr;
   initializeEmptyArray(ptr);
   insertAtIndex(ptr, 0, 4);
   insertAtIndex(ptr, 0, 3);
   insertAtIndex(ptr, 0, 2);
   insertAtIndex(ptr, 0, 1);
   resizeArray(&ptr);
   for (int i = 0; i < capacity; i++)
   {
       printf("%i", arr[i]);
   }
}

这会启动我的数组 [1,2,3,4],然后调用调整大小数组来测试它。

void resizeArray(int **arr)
{
    int *newArr = (int *)malloc(capacity * 2 * sizeof(int));
    for (int i = 0; i < capacity; i++)
    {
        newArr[i] = (*arr)[i];
    }
    for (int i = capacity; i < capacity * 2; i++)
    {
        newArr[i] = EMPTY;
    }
    free(*arr);
    *arr = newArr;
}

问题是 arr 的值在我打印时并没有变成 [1,2,3,4,-1,-1,-1,-1](-1 代表空的)。如何更改指针以指向这个新数组?

Capacity代表数组支持的元素个数,初始为4 EMPTY 定义为-1,代表数组中的空位。

您无法调整数组的大小。它的大小是固定的。

因此,如果您想要可以调整大小的内容,请执行以下操作:

int arr[4]; --> int* arr = malloc(4 * sizeof *arr);

顺便说一句:

您似乎漏掉了一行:

capacity = 2 * capacity ;

看看"realloc",你的问题听起来很完美

代码的两个主要问题是 arrmain() 中分配在堆栈上,然后 free() 它在 resizerArray() 中。这是一个缺陷,我修复了在 main() 中分配 arr 的堆。在您的循环中,您打印 arr[i] 但将 ptr 传递给更新的 resizeArray(),但 arr 仍指向现在已释放的内存。我通过删除 ptr 变量解决了这个问题:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY 0

void resizeArray(int **arr, size_t capacity) {
    int *newArr = malloc(2 * capacity * sizeof(int));
    // for (int i = 0; i < 2 * capacity; i++) {
    //  newArr[i] = i < capacity ? (*arr)[i] : EMPTY;
    // }
    memcpy(newArr, *arr, capacity * sizeof(int));
    memset(newArr + capacity, EMPTY, capacity * sizeof(int));
    free(*arr);
    *arr = newArr;
}

int main(void) {
    size_t capacity = 4;
    int *arr = malloc(capacity * sizeof(int));
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    arr[3] = 4;
    for (int i = 0; i < capacity; i++) {
        printf("before: %d\n", arr[i]);
    }
    resizeArray(&arr, capacity);
    capacity *= 2;
    for (int i = 0; i < capacity; i++) {
        printf("after: %d\n", arr[i]);
    }
}

我注释掉了 resizeArray 中的循环,这样您就可以看到如何做到这一点。代码打印:

before: 1
before: 2
before: 3
before: 4
after: 1
after: 2
after: 3
after: 4
after: 0
after: 0
after: 0
after: 0

resizeArray() 和调用代码都必须知道因子 2。这不是一个伟大的设计。也许传递新旧容量?或者传入 size_t *capacity 如果你想在 resizeArray() 中硬编码这个因素可以更新?请记住检查 malloc() 的 return 值以确保它没有失败。

有关调整堆分配内存大小的标准方法,请参阅 realloc(),有关如何获取预初始化内存的信息,请参阅 calloc()

您不能调整具有自动存储持续时间的数组的大小。您可以使用已分配存储持续时间的数组来执行此操作。

所以你应该删除main中的数组声明并写

int *ptr = malloc( 4 * sizeof( int ) );

int *ptr = malloc( capacity * sizeof( int ) );

您还忘记更改变量的值 capacity。我想它没有声明为常量变量。

在这种情况下,函数 resizeArray 可以通过以下方式查找示例

int resizeArray( int **arr )
{
    int *newArr = realloc( *arr, capacity * 2 * sizeof(int));

    int success = newArr != NULL;

    if ( success ) 
    {
        *arr = newArr;

        for (int i = capacity; i < capacity * 2; i++)
        {
            newArr[i] = EMPTY;
        }

        capacity *= 2;
    }

    return success;
}

注意数组的重新分配可能会失败。所以函数应该向调用者发出重新分配是否成功的信号。

此外,将变量 capacity 用作全局变量也不是一个好主意。

你可以写在 main

int capacity = 4;
int *ptr = malloc( capacity * sizeof( int ) );

// ...

并像

一样调用函数
resizeArray( &ptr, &capacity );

在这种情况下,函数将如下所示

int resizeArray( int **arr, int *capacity )
{
    int *newArr = realloc( *arr, *capacity * 2 * sizeof(int));

    int success = newArr != NULL;

    if ( success ) 
    {
        *arr = newArr;

        for (int i = *capacity; i < *capacity * 2; i++)
        {
            newArr[i] = EMPTY;
        }

        *capacity *= 2;
    }

    return success;
}