"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
.
Возможно ли это как-то преодолеть?
Ответы
Ответ 1
Там нет неявного 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
и другие как методы.
Ответ 2
Типичный подход в 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)
.
Ответ 3
C не работает. Это не объектно-ориентированный язык. Функции, управляющие структурами данных, должны принимать указатель на структуру в качестве аргумента.
Ответ 4
Ваши указатели на функции не являются методами, поэтому у них нет информации о вызывающем объекте. Единственный способ сделать то, что вы хотите, это либо передать указатель на объект, либо сделать этот указатель глобальным (последнее не рекомендуется).
Ответ 5
Поскольку у вас будет только одна структура Stack (которую вы, по-видимому, назвали стеком), вы можете определить ее как глобальную переменную. Это позволит pop/push напрямую ссылаться на переменную стека.
Вы бы сделали что-то вроде:
stack.current_size + = 4;
или используйте оператор → , если вы решите объявить стек как указатель памяти на стек.
Ответ 6
#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;
}
Ответ 7
Очевидно, что вы можете иметь член Stack * в структуре, а затем просто инициализировать его с адресом структуры, прежде чем использовать указатели на функции. Затем сделайте Stack * параметр на указателях функций.