0

I am trying to implement a stack in C using arrays. I want an array of integers, and each time I try to push an int I want to allocate some new memory. But my understanding of malloc() is that it returns a pointer to some memory it allocated somewhere, which would be fine if I had an array of int-pointers, but I don't. Here's where I allocate new memory, and I get a warning:

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

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

Is it possible to implement a stack using a dynamically allocated array of non-pointers? Or does malloc() lend itself to just using an array of pointers?

EDIT: I think I am trying to treat an array like a linked list? Seems when I want to allocate space for an array using malloc, it looks something like malloc(sizeof(int) * maxSize). This will make a big chunk of memory somewhere. What I can't do is ask malloc to give me another piece of memory right at the end of that chunk, but I can expand that chunk. If I were implementing a stack using a linked list, it wouldn't matter WHERE malloc put the new space. I think I'm mixing some things up in my head.

So next question- if implementing a stack using arrays, do I HAVE to specify a maximum size of the stack?

7
  • 2
    Like any data structure, array of ints is just a memory block of an arbitary size without semantics (it is defined by your program, i.e. how you use it). malloc() allows to allocate memory block. Commented Sep 24, 2017 at 16:55
  • 1
    Use realloc... Commented Sep 24, 2017 at 16:56
  • 1
    Please show how stack is declared. And dynamic memory allocation without pointers is somewhat contradictory. Commented Sep 24, 2017 at 16:57
  • 1
    The way you've defined it, stack only has one element. stack[lasti + 1] is invalid. Commented Sep 24, 2017 at 17:18
  • 2
    No, you don't understand arrays, apparently. This has nothing to do with malloc. Commented Sep 24, 2017 at 17:22

4 Answers 4

1

The memory returned by malloc() could be used to store an int array of a certain size. One way to implement your data structure is to allocate a fixed size int array using malloc(). And then, you can insert elements into the array until you reach its maximum size. At this point, you can realloc() (See man page for more details) to resize the previously allocated block for more memory (You can double the previous size par example). Or another technique is to use a multi stage stack which means you add new stack frames to the stack bank whenever the previous stack runs out of space. One other possible way to avoid realloc() (It could fail if handling large sized memory blocks) is to swap the previous stack frame into disk whenever it is full & then use the same frame to insert new values.

An implementation of the realloc() stack :

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

You have to initialize your stack struct before calling insert().
I wrote a demo on ideone.com (Saves file forever) that shows a complete implementation of the stack with an example of inserting 100 elements with an initial size of 25 elements.

Some people suggested to call realloc() for every new insertion. This method is extremely bad because it causes a horrible performance degradation (realloc() is a heavy duty function), especially when the insertion process happens so many times in a unit of time (Insertion overhead).

Sign up to request clarification or add additional context in comments.

Comments

1

You have entirely misunderstood what malloc() does - it returns a pointer to a memory block; you can interpret that memory block how you wish - it is not an array of pointers - the pointer is how you reference the array.

To implement your stack dynamically using a contiguous memory block, you need to resize the allocation using realloc(); however this can be terrifically inefficient since in most cases the existing allocation cannot simply be extended and will require a new larger allocation to be created than all the content of the existing allocation copied to it before deleting the previous allocation. One solution is to extend the stack in "chunks", where the chunk size is a proportion of the current capacity, so that the number of reallocation is adaptive to the usage.

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

The above solution can be adapted to also decrease the capacity dynamically in the pop() when the stack_index falls below a certain proportion of stack_size for example and further perhaps to allow multiple stacks. Some safety checks for the calloc()/realloc() calls could be included, but I have omitted for clarity.

2 Comments

Suggest stack_growth_factor --> STACK_GROWTH_FACTOR and stack = calloc( stack_size, sizeof (int) ) ; to stack = calloc( stack_size, sizeof *stack ) ; for simpler coding, review and maintenance.
@chux : The first is an error - I was part way through changing, when I had to attend to something else. The second I considered but given the apparent confusion over pointers, decided that might be just one more source of confusion at this stage. Will edit later (unless you wish to do so) when I am at a computer rather than a phone.
0

when you declare small array in your main function it goes in the stack memory. Dynamically allocated memory goes into heap and you can allocate memory through pointer. first you declare pointer to int and allocate small memory though malloc and when it is needed you can reallocate memory through realloc().like this

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

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

Always remember to check errors.

5 Comments

You don't need to cast realloc(). And you should assign the result to a different variable, so you can check for errors.
And the "stack memory" is not static.
I meant something else... sorry for that @jens Gustedt
This is a bad idea.
yeah I also know this is bad Idea @Karim But this is a trivial solution.
0

to understand better how a pointer works, let's see and compare two declaration:

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

The second one use pointers:

int *array = NULL;

The pointer "array" store the address in the memory of the first value of an int array. We have to 'manually' allocate some space in the memory, so our process can read and write in this region of memory. To do so let's see this code:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.