是否可以在不显式定义变量来指定长度的情况下创建动态数组?

Is it possible to create a dynamic array without explicitly defining a variable to specify the length?

提问人:Debuholden 提问时间:11/14/2023 更新时间:11/14/2023 访问量:66

问:

我正在尝试创建一个动态数组,可以使用函数 & 进行修改。现在我目前拥有它的方式,我需要一个变量来跟踪它的大小。我对这个概念的实现是将数据/大小存储在结构中,如下所示:Array_Push(array, val)Array_Del(array, index)

struct Array {  
    int *data;  
    int size;  
}

为了读取实际的数组,您必须键入我认为有点多余的内容。array.data[i]

我的解决方案是尝试将数组的大小存储在不同的索引中。我不想将它存储在里面,因为这会造成很多混乱,所以我想尝试将其存储在 .一个明显的问题是它位于阵列之外。相反,我所做的是通过 创建一个数组。之后,我通过 增加指向它的指针。但是,当我尝试释放它时,我最终释放了非编辑内存。我目前的想法是,问题出在某个地方,当我调用函数内部时,它不会修改我的原始指针。如果是这种情况,那么我想知道如何解决这个问题。这是我的代码,以防万一:[0][-1][-1]int *array = malloc(sizeof(int))array += 1free(array)malloc()malloc()

array.h:

#pragma once

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

int *Array_Create() {
  int *array = malloc(sizeof(int));

  // If malloc fails to allocate memory
  if (array == NULL) {
    printf("Error creating array: malloc() failed to allocate memory");
    exit(12);
  }

  array[0] = 0;

  array += 1;

  return array;
}

void Array_Push(int *array, int value) {
  if (array[-1] == 0) {
    array = malloc(sizeof(int));
  } else {
    // array = realloc(array, sizeof(int) * array[-1]);
    printf("ERROR READING ARRAY SIZE IN: Array_Push()");
  }
}

main.c:

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

#include <dynamic_array.h>

int main() {
  int *array = Array_Create();

  printf("%d", array[-1]);

  Array_Push(array, 1);

  free((array - 1));
  free(array);

  return 0;
}
C 指针 malloc 动态数组

评论

2赞 Lundin 11/14/2023
初始结构没有错。你在这里把简单的事情做得太复杂了,这是糟糕的工程。我会退后一步,而是选择最简单的实现,使用C语言中成熟的最佳实践。
0赞 Debuholden 11/14/2023
我知道这没有错。我只是觉得拥有它有点多余,所以我想尝试修复它。我的问题很简单:这可能吗?如果是这样,那么:你能向我解释一下吗?
0赞 Lundin 11/14/2023
正确的解决方案不是试图“修复”C,而是按原样使用它。但是,给出一些最不丑陋的修复方法可能是使用宏: .以及如何键入.typedef struct { ... } array; array arr;#define arr arr.dataarr[i]
0赞 chux - Reinstate Monica 11/14/2023
@Debuholden,in 除了分配内存然后泄漏内存外,没有任何用途。的新赋值不会以任何方式影响调用代码。array = malloc(sizeof(int));Array_Push()array
0赞 chux - Reinstate Monica 11/14/2023
@Debuholden,如果你想要一个 的“动态数组”,它的动态长度会被限制为 吗?目前,大小的“动态数组”限制为 ,但真正的数组大小限制为 。charCHAR_MAXintINT_MAXSIZE_MAX

答:

3赞 Eric Postpischil 11/14/2023 #1

你对数组的使用和建议你认为数组的各个元素可以被分配和释放,或者你对内存分配有一些其他概念上的错误。mallocfree

malloc为您提供内存块的地址,并且您必须将该地址传递给 。不能将该块中的任何其他地址传递给 。可以将一个地址添加到地址并将其用于索引,但是,当您将地址传递给 时,必须通过减去 1 来重建原始地址。freefreefree

Array_Create可以是:

int *Array_Create(void)
{
    int *array = malloc(sizeof *array);
    if (!array)
    {
        fprintf(stderr, "Error creating array:  malloc failed to allocate memory.\n");
        exit(EXIT_FAILURE);
    }
    array[0] = 0;
    return array +1;
}

并且可以是:Array_Push

int *Array_Push(int *array, int value)
{
    int *temp = realloc(array-1, (array[-1] + 1) * sizeof *temp);
        // Note use of array-1 when passing address to realloc.
    if (!temp)
    {
        fprintf(stderr, "Error growing array:  realloc failed to allocate memory.\n");
        exit(EXIT_FAILURE);
    }
    array = temp+1;
    ++array[-1];
    array[0] = value;
    return array;
}

释放数组时,应仅使用 ,而不应使用 。free(array-1)free(array)

请注意,需要为 提供一个新值,因此我编写了它以返回该值。调用它时,应将其称为 。也可以将其写成接受指向 的指针,如 in 和 称为 。这需要对其代码进行相应的更改。Array_Pusharrayarray = Array_Push(array, value);arrayvoid Array_Push(int **array, int value);Array_Push(&array, value);

也就是说,优秀的程序员会避免这种安排,因为设计、工程和质量的原因超出了这个答案的范围。在某些情况下可能会使用这种代码,但您通常希望避免这样的错误。

评论

1赞 Eric Postpischil 11/14/2023
@nielsen:哎呀,错过了,谢谢。固定。
0赞 tstanisl 11/15/2023
如果不是最鼓励的做法,则将其放入库代码中。exit(EXIT_FAILURE)
0赞 Eric Postpischil 11/15/2023
@tstanisl:它不是库代码,Stack Overflow 是用来回答特定问题的,而不是提供完成的生产代码。答案中的代码应侧重于特定问题。
0赞 tstanisl 11/15/2023
我同意这里无关紧要。但仍然值得一提的是,拨打隐藏电话并不是一个好习惯。exit()
0赞 Eric Postpischil 11/15/2023
@tstanisl:这并不是普遍的“不是一个好的做法”。这取决于应用程序。我对那些推动设计新手理论的人没有兴趣。要知道,并不是每个人都在你所从事的特定编程子领域中练习,也不是每个程序都应该被编写成以你希望它们处理的任何特定方式处理所有可能的事件。并非每个程序都需要处理所有可能的输入或尝试从所有可能的故障中恢复。