簡體   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