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

问题描述 投票:0回答:2

我正在尝试创建一个动态数组,可以使用函数

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 += 1
增加指向它的指针。然而,当我尝试用
free(array)
释放它时,我最终释放了非
malloc()
ed 内存。我目前的想法是,问题在于当我在函数内调用
malloc()
时,它不会修改我的原始指针。如果是这种情况,那么我想知道如何解决这个问题。这是我的代码,以防有帮助:

数组.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 pointers malloc dynamic-arrays
2个回答
0
投票

您对

malloc
free
的使用表明您认为可以分配和释放数组的各个元素,或者您对内存分配有一些其他概念错误。

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

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
可以是:

void 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;
}

释放数组时,应仅使用

free(array-1)
,而不是
free(array)

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


0
投票

您最初的想法是最正确的,但我会使用灵活数组成员并为数组大小和当前使用的大小使用单独的成员。

typedef struct 
{
    size_t size;
    size_t c_index;
    int data[];
}Array_t;

它将:

  1. 简化分配和释放(只需要一个free)
  2. 减少 malloc 调用次数,因为您可以增加多个元素的大小。
  3. 使其更易于阅读和维护
© www.soinside.com 2019 - 2024. All rights reserved.