1

我在 C 中有一个任务来实现抽象数据类型 STACK。数据类型的性质需要需要分配内存的键结构。我的问题是,我的导师现在坚持让初始化函数接收一个指向键结构的指针。init() 函数只会分配结构所需的内存并将字段设置为零,但传入的指针需要分配该内存位置。

如果不让函数返回指针或传入 2 星指针,我想不出一种方法来做到这一点——这两者都是不允许的。我知道函数原型必须是(其中 stackT* 是指向关键堆栈数据结构的指针):

    void init(stackT* stack);

我想出了这个,它工作正常:

    void init(stackT** stack){
        *stack = (stackT*) malloc(sizeof(stack));
        (*stack)->count = 0;
        return;
    }

但它不遵守分配的限制。


tl;博士版本:

基本上,如何将原始指针的地址传递给 STACK 数据结构 (&stackPtr) 到一个函数中,该函数将一星指针作为参数而不得到指针类型的警告?此外,一旦您将参数更改为(stackT* stack)以下代码,即使我以两种方式传递相同的东西,它也不起作用 - 这就是我的问题所在。

我认为如果您打算将指针传递给指针,则需要将参数作为 2 星指针。当您取消引用指针时,编译器必须知道它正在处理什么。

无论如何,鉴于限制,我不确定如何做到这一点。在我看来,这只会让它变得不必要地更加困难。

4

4 回答 4

3

正如评论中指出的那样,我相信您没有达到目的。

我认为这个想法是“根”stackT实例应该是一个众所周知的结构,以便您可以在本地声明一个。然后调用init()以设置stackT实例描述的实际堆栈:

int push_four(void)
{
  stackT my_stack;

  init(&my_stack);
  push(&my_stack, 1);
  push(&my_stack, 2);
  push(&my_stack, 3);
  push(&my_stack, 4);
}

以上假设堆栈存储整数,即里面的分配init()应该是这样的:

void init(stackT *stack)
{
  stack->items = malloc(64 * sizeof *items);
  stack->count = 0;
}

而这反过来又假设如下声明:

typedef struct {
  int *items;
  size_t count;
} stackT;

当然,默认的最大深度 (64) 应该是 的参数init(),您必须检查(但不能强制转换!) 的返回值malloc(),依此类推。

于 2013-09-11T12:59:44.100 回答
2

通常,当您拥有复杂的结构时,就会有一个控件struct,并且该控件将具有指向实际内存的指针。

例子:

struct stack_control_s {
    void * memory;
    size_t memory_size;
    size_t current_size;
};

然后你将一个指向控制结构的指针传递给你的初始化器并让它做真正的工作;

#define STACK_MIN_SIZE 0x100
int stack_init(struct stack_control_s * stack) {
    memset(stack, 0, sizeof(*stack));

    stack->memory = calloc(STACK_MIN_SIZE, 1);

    if (!stack->memory)
        return -1; //error

    stack->memory_size = STACK_MIN_SIZE;

    return 0; // all good
}

这是我曾经制作的通用 C 列表的稍微修改的标题。我已添加到宏以使其可用作堆栈。也许这会给你一些启发:

list_t.h

利用:

list_t(char) mylist;
list_init(&mylist);

list_push(&mylist, 'A');

printf("%c\n", list_pop(&mylist));
于 2013-09-11T13:00:13.303 回答
1

这将指针分配给堆栈定义的地址并传递要初始化的指针(使用单个 * :)... 这对您有用吗?

#include <ansi_c.h>  
typedef struct  {
    int count;
} COUNT;

typedef struct  {
    COUNT count;
    int *element1;
    int *element2;
    int address;
} STACK;

STACK stack, *pStack;

void InitStack(STACK *iS);

int main(void)
{    //This is how I think you will meet the 
     //criteria you are talking about (single *)
    pStack = &stack; //assigning address of stack to pointer

    InitStack(pStack);
    //pStack->address == pStack
    return 0;
}

void InitStack(STACK *iS)
{
    iS->count.count = 0;
    iS->address = (int)iS; //assigning address of stack to member of struct
    iS->element1 = calloc(10, sizeof(int));
    iS->element2 = calloc(10, sizeof(int));
}
于 2013-09-11T14:31:46.783 回答
1

可能它不是最好的解决方案,但您可以全局定义您的堆栈。

在这种情况下,它看起来像:

stackT G_stack;
....

void init(stackT* stack){
    stack->count = 0;
    return;
}

int main() {
    .....
    init(&G_stack);
    .....
}

在这种情况下,您不需要更改原型。

于 2013-09-11T13:02:08.603 回答