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

时间:2017-09-24 16:53:15

标签: c arrays pointers memory-management stack

我正在尝试使用数组在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放置新空间并不重要。我想我正在混合一些东西。

接下来的问题 - 如果使用数组实现堆栈,我是否必须指定堆栈的最大大小?

4 个答案:

答案 0 :(得分:1)

SELECT * FROM @T WHERE ID = @YourID AND Name = @YourName UNION ALL SELECT * FROM @T WHERE ID = @YourID; 返回的内存可用于存储特定大小的malloc()数组。实现数据结构的一种方法是使用int分配固定大小的int数组。然后,您可以将元素插入到数组中,直到达到其最大大小。此时,您可以malloc()(请参阅手册页以获取更多详细信息)来调整先前分配的块的大小以获得更多内存(您可以将先前大小的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; } 之前,您必须初始化堆栈结构 我在ideone.com(永久保存文件)上编写了一个演示,演示了一个完整的堆栈实现,其中插入了100个元素,初始大小为25个元素。

有些人建议每次新插入时拨打insert()。这种方法非常糟糕,因为它会导致可怕的性能下降(realloc()是一个重载函数),尤其是当插入过程在一个单位时间内发生很多次时(插入开销)。

答案 1 :(得分:1)

你完全误解了malloc()的作用 - 它返回一个指向内存块的指针;你可以解释你想要的内存块 - 它不是指针数组 - 指针就是你引用数组的方式。

要使用连续的内存块动态实现堆栈,您需要使用realloc()调整分配大小;然而,这可能是极其低效的,因为在大多数情况下,现有的分配不能简单地扩展,并且需要创建新的更大的分配,而不是在删除先前的分配之前复制到它的现有分配的所有内容。一种解决方案是在" chunks"中扩展堆栈,其中块大小是当前容量的一部分,因此重新分配的数量适应于使用。

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

pop()低于stack_index的某个比例时,上述解决方案还可以适应 例如{1}}并且可能还允许多个堆栈。可以包含对stack_size / calloc()来电的一些安全检查,但为了清楚起见,我省略了。

答案 2 :(得分:0)

当你在main函数中声明小数组时,它会进入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

始终记得检查错误。

答案 3 :(得分:0)

更好地理解指针是如何工作的,让我们看看并比较两个声明:

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

第二个使用指针:

int *array = NULL;

指针“array”将地址存储在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;
}