views:

240

answers:

7

Let's say that I have the following code in C that represents a stack :

#define MAX 1000

int arr[MAX];
static int counter = 0;
isstackempty()
{
    return counter <= 0;
}
void push(int n)
{
    if (counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return;
    }
    arr[counter++] = n;
}

int pop(int* n)
{
    if(isstackempty() || n == 0) {
        printf("Stack is empty\n");
        return 0;
    }
    *n = arr[--counter];
    return 1;
}

The above code is in a stack.c file and the function prototypes are in a header.


Now, coming from a C# and OO background, if I would want to separate stacks to use in my application, in an OO language I would create two instances. But in C, how do you handle such a scenario?

Say I want to use two separate stacks in my C code...with the above code, how would I go about it?

+10  A: 

Put the array arr inside a struct.

struct stack {
    int arr[MAX];
    ...
}

This struct becomes your instance. You can then declare it on the stack:

struct stack mystack;

or on the heap using malloc:

struct stack *mystack = malloc(sizeof(struct stack));

You also need to pass a pointer to the instance as the first parameter to any function manipulating the instance.

JesperE
better yet, use a typedef to name the struct
anon
@Neil: I think you're right, but not everyone does.
JesperE
@Jesper Really? I've never met anyone with that opinion.
anon
Try Mr. Torvalds.
JesperE
what does he have against it?
Carson Myers
See "Typedef is evil" here: http://www.linuxjournal.com/article/5780.
JesperE
A: 

Simply make your 'this' pointer explicit:

struct stack* create_stack();
void push(struct stack* mystack, int n);
void pop(struct stack* mystack, int* n);
Kristof Provost
But please use a proper type instead of void.
JesperE
+1  A: 

I hope you find this paper useful. It gives more than one answer to your question :)

Sixteen Ways to Stack a Cat

AraK
+6  A: 

The C way to do this is to wrap up all the state for your 'object' into a struct, and then explicitly pass it into all the functions that operate on stacks, so it should be:

typedef struct _stack {
  int arr[MAX];
  int counter;
} stack;

int isstackempty(stack *s)
{
    return s->counter <= 0;
}

int push(stack *s, int n)
{
    if (s->counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return -1;
    }
    arr[s->counter++] = n;
    return 0
}

int pop(stack *s, int *n)
{
    if(isstackempty(s) || n == 0) {
        printf("Stack is empty\n");
        return -1;
    }
    *n = arr[--s->counter];
    return 0;
}

The issue with your example is you're writing the function definitions like we have a class-based object structure, which C doesn't have. The easiest way to think about how it's done in C is that you're writing methods that require you to explicitly pass in the 'this' parameter.

Also you can have the equivalent of constructors and destructors, which can further abstract your 'object'.

stack* newStack() {
    stack* s = malloc(sizeof(stack));
    s->counter = 0;
    return s;
}

void freeStack(stack* s) {
    free(s);
}
Falaina
You can skip _stack in your typedef: `typedef struct { ... } stack;`
JesperE
Ah, true. Force of habit cause I"m used to defining self-referntial structs. It'd probably be a bit cleaner to omit it in this cause, though.
Falaina
+3  A: 

One (extremely simplistic) way of going about it is to define a struct that represents a stack:

typedef struct {
    int arr[MAX];
    int counter = 0;
} myStack;

and then rewrite push() and pop() to operate on an instance of myStack:

int push(myStack *s, int n)
{
    if (s->counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return -1;
    }
    s->arr[(s->counter)++] = n;
    return s->counter;
}

int pop(myStack *s, int* n)
{
    if(0 == s->counter || 0 == n) {
        printf("Stack is empty\n");
        return -1;
    }
    *n = s->arr[--(s->counter)];
    return 1;
}

(Also added a meaningful return value and error value to push(). YMMV.)

Meredith L. Patterson
A: 

My answer to this other question has a complete working example of an OO data buffer structure in C.

Software Monkey
A: 

A dynamically allocated structre-per-instance is the right way to go. A point of detail - if you are writing a more generally used API it is probably a good idea to engage in data hiding for better abstraction. The simplest way of doing this is keep the definition of the internal structure in the C file (or a private header file), and typedef a void pointer to (e.g.) 'stack_handle_t'. It is this type that is returned from your 'constructor' and is passed back in to each other function. The implementation is aware that the value of the handle is in fact a pointer to a structure and at the beginning of each function simply does:

int pop(stack_handle_t handle, int* n)
{
    stack *p_stack = (stack *)handle;
    ...

Even better than that is to use an internally allocated identifier instead, whether this is an index into an array of these structs or simply an identifier which can be matched against one of a (linked?) list of structs. Obviously all this is irrelevant if its only for use internal to your project, in those circumstances it is just making unnecessary work and over-complication.

WillW