我试图使用void指针在C中实现一个通用堆栈,并试图通过将所有责任委托给函数调用方并避免更复杂的方法来保持它尽可能简单。
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
struct Stack {
void *data;
struct Stack *next;
};
/*
* We declare a pointer to a Stack structure thereby making use of incomplete
* types. Clients that pull in stack.h will be able to declare variables of type
* pstack which are pointers to pointers to Stack structures.
* */
typedef struct Stack *pstack;
bool is_empty(pstack *s);
void make_empty(pstack *s);
void push(struct Stack **s, void *new_num);
void *pop(pstack *s);
#endif /* STACK_H */#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
bool is_empty(pstack *s) { return !s; }
void make_empty(pstack *s)
{
if (!is_empty(s))
pop(s);
}
void *pop(pstack *s)
{
struct Stack *tmp;
void *i;
if (is_empty(s))
exit(EXIT_FAILURE);
tmp = *s;
i = (*s)->data;
*s = (*s)->next;
free(tmp);
return i;
}
void push(struct Stack **s, void *new_num)
{
struct Stack *new_node = malloc(sizeof(struct Stack));
if (!new_node)
exit(EXIT_FAILURE);
new_node->data = new_num;
new_node->next = *s;
*s = new_node;
}#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int main(void)
{
pstack s1;
void *n;
int i = 1;
int j = 2;
push(&s1, &i);
push(&s1, &j);
n = pop(&s1);
printf("Popped %d from s1\n", *((int *)n));
n = pop(&s1);
printf("Popped %d from s1\n", *((int *)n));
exit(EXIT_SUCCESS);
}发布于 2015-07-09 17:33:43
/*
* We declare a pointer to a Stack structure thereby making use of incomplete
* types. Clients that pull in stack.h will be able to declare variables of type
* pstack which are pointers to pointers to Stack structures.
* */这里有几个问题。首先,pstack类型的变量只是指向Stack结构的指针,而不是注释声明中指向指针的指针。其次,您没有按预期使用不完全类型:客户端仍然看到struct Stack的实现,实现中的任何更改都会导致客户端代码无缘无故地重新编译。处理它的一个标准方法是离开。
typedef struct Stack stack;在头文件stack.h中,并声明
struct Stack {
...
};在实现文件stack.c中。
发布于 2015-07-10 13:40:51
这不是一个有效的程序,您有几个bug。另外,程序设计不是实现不透明类型的正确方法。
typedef struct stack_t stack_t;stack_t类型的对象。exit(EXIT_FAILURE);是非常值得怀疑的实践。相反,您应该使用返回的错误代码来实现您的函数,并让调用方担心要采取的操作。if(!is_empty(s))必须是while (!is_empty(s))。pop不会修改指针(它不能),因此空指针永远不会设置为NULL。stack_t。取决于编码风格。所以在h文件中应该有类似于typedef struct stack_t stack_t;的东西#include放在h文件中,以显示模块对其他库的依赖关系。!运算符来比较整数或指针,它应该只用于布尔逻辑。相反,对于指针的空检查应该是显式的,s == NULL。{ }或循环之后始终使用大括号if (又称“复合语句”)。不这么做的人迟早会写错误。把苹果的"goto fail“错误看作一个完美的例子。我不认为那个写了10亿美元的错误的人是个新手,而是一个傲慢的老兵,他坚持不使用牙套,没有什么好的理由。return语句,但main()中的返回始终是正确的。https://codereview.stackexchange.com/questions/96357
复制相似问题