chevron_left chevron_right
Login Register invert_colors photo_library


Stay updated and chat with others! - Join the Discord!
Thread Rating:
  • 0 Vote(s) - 0 Average


Variable type stacks in C (complete code) filter_list
Author
Message
Variable type stacks in C (complete code) #1
Variable type stacks are what is used for actual system stacks. They allow you to say, push an int, then a char, then another int, etc...

So, how do they work?

As you recall, for our last three stack tutorials we used arrays to handle our data. In this case, we won't. This is where we will stop using the stack pointer as a count.

So, what is a stack pointer (really)?
A stack pointer simply points to the next available location on the stack. This is almost the same definition as we used in the other cases, except the stack pointer ALWAYS incremented by 1 when we did that.

Let's take a look at our structure..

Code:
struct myStack
{
     int *data;
     int sp;
};

Now, in this tutorial, we wont be using int pointers. We will use the "pointer to anything", or a void pointer. Another thing, we no longer have to keep track of the stack origin. Since every programmer ensures his stack is balanced, we won't have to. We will for this just for safety. Here is our updated structure:

Code:
struct myStack
{
     void *base;
     void *sp;
};

here, we replaced the type of the data with a void pointer, but we also changed the type of the stack pointer. Why?
Well, since this one doesn't have a type, we can't address it in array mode. This stack will work by offset. sp will ALWAYS point to the next open space, instead of the next open slot on the array. If you wanted to determine the offset, it will be (sp - base).

Now, let's write our header file.

Code:
#include <stdlib.h> //for size_t

char myStack_init(struct myStack *stack_object, unsigned int size); //0 if success, 1 if alloc failure
void myStack_push(struct myStack *stack_object, void *obj, size_t size);
void myStack_pop(struct myStack *stack_object, void *dst, size_t size);
void myStack_destroy(struct myStack *stack_object);

/*these are shorthand functions, you can make more*/
#define myStack_push_int(a, b) myStack_push(a, b, sizeof(int))
#define myStack_pop_int(a, b) myStack_pop(a, b, sizeof(int))

Now, if you didn't notice, we changed all of the input objects to void pointers. This is because we don't know what type we are going to be sending or receiving, so we have to make them a universal type. Another thing to notice is that we added a third parameter (size). Since we are using void *'s, they don't have inherent sizes attached to them, so the user has to specify how large the data is.

The #define lines are just ways to simplify it. You can add these for whatever types you want, or not use them at all. No code has to be written for these functions (they're really just macros).

Alright. Since I hope you read the first three turorials already (or at least the first one), I shouldn't have to comment EVERY single line. If you don't understand memcpy, take a look at this page so that it isn't over your head. We will use this a lot.

Code:
#include "myStack.h"
#include <stdlib.h>

char myStack_init(struct myStack *stack_object, size_t size)
{
     if (size < 1) return 1;
     if ((stack_object->sp = stack_object->base = malloc(size)) == NULL)
          return 1;
     return 0;
}

void myStack_push(struct myStack *stack_object, void *obj, size_t size)
{
     /* check if the user pushed a NULL object (bad) */
     if (obj == NULL) return;

     /* push it on */
     memcpy(stack_object->sp, obj, size);

     /* update the pointer */
     stack_object->sp += size;
}

void myStack_pop(struct myStack *stack_object, void *dst, size_t size)
{
     /* check if the user sent a NULL object (bad) */
     if (dst == NULL) return;

     /* update the stack pointer */
     stack_object->sp -= size;

     /* copy the data */
     memcpy(dst, stack_object->sp, size);
}

void myStack_destroy(struct myStack *stack_object)
{
     free(stack_object->base); //for unbalanced stack possibility
}

and using it:

Code:
#include <stdio.h>
#include "myStack.h"

int main()
{
     int a = 1, b = 2, c = 258, a2, b2, c2;
     char d = 'a', d2;
     float e = 3.14, e2;
     struct myStack stk;

     myStack_init(&stk, 20); //our stack can handle 20 bytes

     /* push objects */
     myStack_push(&stk, &a, sizeof(int));
     myStack_push(&stk, &b, sizeof(int));
     myStack_push(&stk, &c, sizeof(int));
     myStack_push(&stk, &d, sizeof(char));
     myStack_push(&stk, &e, sizeof(float));

     /* pop off */
     myStack_pop(&stk, &e2, sizeof(float));
     myStack_pop(&stk, &d2, sizeof(char));
     myStack_pop(&stk, &c2, sizeof(int));
     myStack_pop(&stk, &b2, sizeof(int));
     myStack_pop(&stk, &a2, sizeof(int));

     /* display them */
     printf("a: %d\tb: %d\t c: %d\nd: %c\ne: %f\n",
               a2, b2, c2, d2, e2);

     /* destroy the stack */
     myStack_destroy(&stk);

     return 0;
}

I know, its basic, and not very explained. If you want a tutorial on how they work, comment and one will be written.

[+] 1 user Likes phyrrus9's post
Reply

RE: Variable type stacks in C (complete code) #2
That's a nice share mate.

Reply






Users browsing this thread: 1 Guest(s)