"this" указатель в C (не С++)

Я пытаюсь создать стек в C для удовольствия, и придумал идею использования структуры для представления стека. Затем я добавляю указатели на функции для операций push() и pop().

Пока все хорошо, кажется, но для реализации функций push() и pop() мне нужно как-то ссылаться на *. Как это можно сделать (может?)?

Это моя структура

struct Stack {
 int *data;
 int current_size;
 int max_size;
 int (*push)(int);
 int (*pop)();
};

И как пример здесь нажмите

int push(int val) {
 if(current_size == max_size -1)
 return 0;
 data[current_size] = val;
 current_size++;
 return 1;
}

Как вы можете себе представить, компилятор понятия не имеет, что такое current_size, так как он ожидал бы что-то вроде stack->current_size.

Возможно ли это как-то преодолеть?

7 ответов

Там нет неявного this в C. Сделайте его явным:

int push(Stack* self, int val) {
 if(self->current_size == self->max_size - 1)
 return 0;
 self->data[self->current_size] = val;
 (self->current_size)++;
 return 1;
}

Конечно, вы должны передать указатель на структуру в каждый вызов push и аналогичные методы.

Это, по сути, то, что компилятор С++ делает для вас, когда вы определяете Stack как класс и push и другие как методы.


Типичный подход в C состоит в том, чтобы функции ожидали this как первый параметр.

int push(Stack *self, int val) 
{
 if (self->current_size == self->max_size -1) return 0;
 self->data[self->current_size++] = val;
 return 1;
}

Это имеет дополнительное преимущество: если вам не нужен полиморфизм, вам не нужно помещать функции в стек, потому что вы можете просто вызвать push(stack, 10) вместо stack->push(stack,10).


C не работает. Это не объектно-ориентированный язык. Функции, управляющие структурами данных, должны принимать указатель на структуру в качестве аргумента.


Ваши указатели на функции не являются методами, поэтому у них нет информации о вызывающем объекте. Единственный способ сделать то, что вы хотите, это либо передать указатель на объект, либо сделать этот указатель глобальным (последнее не рекомендуется).


#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct _foo
{
 int q;
 void (*Bar)();
} Foo;
Foo * This;
Foo * foo(Foo * f)
{
 This = f;
 return f;
}
void Bar()
{
 printf("%i\n",This->q);
 This->q++;
}
Foo * FooNew()
{
 Foo * foo = malloc(sizeof(Foo));
 foo->q = 1;
 foo->Bar = &Bar;
}
int main()
{
 Foo *f = FooNew();
 Foo *g = FooNew();
 foo(f)->Bar();
 foo(f)->Bar();
 foo(f)->Bar();
 foo(g)->Bar();
 foo(g)->Bar();
 foo(g)->Bar();
 return 0;
}
</malloc.h></stdlib.h></stdio.h>


Поскольку у вас будет только одна структура Stack (которую вы, по-видимому, назвали стеком), вы можете определить ее как глобальную переменную. Это позволит pop/push напрямую ссылаться на переменную стека.

Вы бы сделали что-то вроде:

stack.current_size + = 4;

или используйте оператор , если вы решите объявить стек как указатель памяти на стек.


Очевидно, что вы можете иметь член Stack * в структуре, а затем просто инициализировать его с адресом структуры, прежде чем использовать указатели на функции. Затем сделайте Stack * параметр на указателях функций.

licensed under cc by-sa 3.0 with attribution.