繁体   English   中英

如何在C中为int(不是int *)数组动态分配内存?

[英]How can I dynamically allocate memory for an array of int (not int*) in C?

我正在尝试使用数组在C中实现堆栈。 我想要一个整数数组,每次尝试推入int时,我都要分配一些新的内存。 但是我对malloc()理解是,它返回一个指向它在某处分配的内存的指针,如果我有一个int指针数组,那很好,但是我没有。 这是我分配新内存的地方,并且收到警告:

int stack[] = {1};  // stack is allocated like this

stack[lasti + 1] = malloc(sizeof(int));  // assignment makes integer from pointer without a cast

是否可以使用动态分配的非指针数组来实现堆栈? 还是malloc()本身适合使用指针数组?

编辑:我想我想像一个链表对待数组? 似乎当我想使用malloc为数组分配空间时,它看起来像malloc(sizeof(int) * maxSize) 这将在某处占用大量内存。 我不能做的是让malloc在该块的末尾再给我一块内存,但是我可以扩展该块。 如果我使用链表实现堆栈,则malloc将新空间放在哪里都没关系。 我想我脑子里有些混乱。

因此,下一个问题-如果使用数组实现堆栈,是否必须指定堆栈的最大大小?

malloc()返回的malloc()可用于存储一定大小的int数组。 实现数据结构的一种方法是使用malloc()分配固定大小的int数组。 然后,您可以将元素插入数组,直到达到其最大大小。 此时,您可以realloc() (有关更多详细信息,请参见手册页)以调整先前分配的块的大小,以获取更多的内存(您可以将先前的size par示例增加一倍)。 或者另一种技术是使用多级堆栈,这意味着每当前一个堆栈空间不足时,就将新的堆栈帧添加到堆栈库中。 避免realloc()另一种可能方法realloc()如果处理大容量的内存块可能会失败)是在磁盘空间已满时将前一个堆栈帧交换到磁盘中,然后使用同一帧插入新值。

realloc()堆栈的实现:

#define SCALE_FACTOR 2  /*  Double stack size at each new realloc   */

typedef struct stack {

    int *array;
    int stack_size;     /* Maximum number of elements */
    int stack_pointer;

} Stack;


int insert(Stack *ptr, int value)
{
    if(ptr->stack_pointer >= ptr->stack_size) {
        int realloc_size = ptr->stack_size * SCALE_FACTOR;
        int *new_array = realloc(ptr->array, realloc_size * sizeof(int));

        if(!new_array)
            return -1;   /* Resizing failed */

        ptr->array = new_array;
        ptr->stack_size = realloc_size;     
    }

    ptr->array[ptr->stack_pointer++] = value;
    return ptr->stack_pointer;
}

您必须在调用insert()之前初始化堆栈结构。
我在ideone.com (永远保存文件)上编写了一个演示,演示了堆栈的完整实现,并以插入100个元素(初始大小为25个元素)为例。

有人建议为每个新插入都调用realloc() 该方法非常糟糕,因为它会导致可怕的性能下降(realloc()是一种繁重的功能),尤其是当插入过程在一个时间单位内发生了如此多次(插入开销)时。

您完全误解了malloc()作用-它返回一个指向内存块的指针; 您可以按自己的意愿解释该内存块-它不是指针数组 -指针是您引用数组的方式。

要使用连续的内存块动态实现堆栈,您需要使用realloc()来调整分配大小; 但是,这在效率上是无效的,因为在大多数情况下,不能简单地扩展现有分配,并且将需要创建比在删除先前分配之前复制到现有分配中的所有内容都更大的新分配。 一种解决方案是以“块”形式扩展堆栈,其中块大小是当前容量的一部分,以便重新分配的数量适合于用法。

#define INITIAL_STACK_SIZE 128
#define STACK_GROWTH_FACTOR 8

static int stack_size = INITIAL_STACK_SIZE ;
static int* stack = 0 ;
static int stack_index = 0 ;

void create()
{
    stack_size = STACK_GROWTH_FACTOR ;
    stack = calloc( stack_size, sizeof(int) ) ;
}

void destroy()
{
    free( stack ) ;
    stack = 0 ;
    stack_index = 0 ;
    stack_size = 0 ;
}

void push( int i )
{
    if( stack != 0 )
    {
        if( stack_index >= stack_size )
        {
            stack_size += stack_size / STACK_GROWTH_FACTOR ;
            stack = realloc( stack, stack_size * sizeof(int) ) ; 
        }

        stack[stack_index] = i ;
        stack_index++ ;
    }
}

int pop()
{
    int i = 0 ;
    if( stack != 0 )
    {
        i = stack[stack_index] ;
        stack_index-- ;
    }

    return i ;
}

例如,当stack_index下降到stack_size的某个比例以下时,上述解决方案也可以适用于动态减小 pop()容量 ,并且可能还允许多个堆栈。 可以包括对calloc() / realloc()调用的一些安全检查,但为清楚起见,我将其省略。

当您在主函数中声明小数组时,它会进入stack memory 动态分配的内存进入堆,您可以通过指针分配内存。 首先,您声明pointer to int并通过malloc分配小内存,并且在需要时可以通过realloc()重新分配内存。

 int* stack=malloc(sizeof(int));

 stack=realloc(stack,(size+1)*sizeof(int)); //size is the size of stack

永远记得检查错误。

为了更好地了解指针的工作原理,我们来看一下两个声明:

int array[10];//note that we know the size of the array

第二个使用指针:

int *array = NULL;

指针“数组”将地址存储在int数组的第一个值的内存中。 我们必须“手动”在内存中分配一些空间,以便我们的进程可以在此内存区域中进行读写。 为此,让我们看下面的代码:

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

int *dynamic_int_array_allocation(int *array, int size){

  if(size == 0){
    // if the size specified by the size variable is 0 then allocate
    // memory for one int, the size of this int in the memory is 2 or 4 bytes
    // it depend on your platform
    // if you want to know how many bytes their was used, use the following:
    // printf("The size of int in this platform is %lu\n", sizeof(int));
    array = (int*)malloc(sizeof(int));
  }
  else if(size != 0){
    // else if the size specified by the size variable is not 0
    // then we have to realloc our integer array, to do so
    // we declare a temporary integer pointer here:
    int *t1;
    // we reallocate our previous pointer with the size variable
    t1 = realloc(array, size * sizeof(int));
    // if the request failed (realloc return null) we free our array
    // if the request succeed we assign to our array pointer the address of
    // the new area of memory returned by the realloc function
    if(array == NULL)
      free(array);
    else
      array = t1;

  }
  return array; // return the address of the array
}

//to test our function:
int main(int argc, char const *argv[]) {
  // declaration of our array
  int *my_integer_array = NULL;

  // allocate a new area of memory to our array
  my_integer_array = dynamic_int_array_allocation(my_integer_array, 0);
  printf("This is the first address of our pointer is: %p\n", my_integer_array);
  // to test our function, we use here a for loop
  for (int i = 0; i < 10; i++) {
    // this realloc our tab at each iteraction
    // we use i+1 because "i" was at 0 and we want
    // the function to reallocate our array with 2 boxes at the beginning of this loop
    // at the end of the loop i will be 9 and we will have 10 boxes in our array
    // wich is ok
    my_integer_array = dynamic_int_array_allocation(my_integer_array, i+1);
    // we fill the boxes of our array with integers
    my_integer_array[i] = i;
    printf("The new address of our pointer is: %p\n", my_integer_array);
  }
  // What is in our array:
  for (int i = 0; i < 10; ++i)
  {
    printf("array[%d] = %d\n",i, my_integer_array[i] );
  }
//don't forget to free the zone of allocated memory
  free(my_integer_array);
  return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM