Подтвердить что ты не робот

"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.

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

4b9b3361

Ответ 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 * параметр на указателях функций.