这是使用链接列表的Stack实现的完整代码。这是来自James Aspnes的耶鲁大学的数据结构笔记(这有什么用的吗?)
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct elt {
struct elt *next;
int value;
};
/*
* We could make a struct for this,
* but it would have only one component,
* so this is quicker.
*/
typedef struct elt *Stack;
#define STACK_EMPTY (0)
/* push a new value onto top of stack */
void
stackPush(Stack *s, int value)
{
struct elt *e;
e = malloc(sizeof(struct elt));
assert(e);
e->value = value;
e->next = *s;
*s = e;
}
int
stackEmpty(const Stack *s)
{
return (*s == 0);
}
int
stackPop(Stack *s)
{
int ret;
struct elt *e;
assert(!stackEmpty(s));
ret = (*s)->value;
/* patch out first element */
e = *s;
*s = e->next;
free(e);
return ret;
}
/* print contents of stack on a single line */
void
stackPrint(const Stack *s)
{
struct elt *e;
for(e = *s; e != 0; e = e->next) {
printf("%d ", e->value);
}
putchar('\n');
}
int
main(int argc, char **argv)
{
int i;
Stack s;
s = STACK_EMPTY;
for(i = 0; i < 5; i++) {
printf("push %d\n", i);
stackPush(&s, i);
stackPrint(&s);
}
while(!stackEmpty(&s)) {
printf("pop gets %d\n", stackPop(&s));
stackPrint(&s);
}
return 0;
}
我可以理解大部分代码。但我无法绕过这一部分
typedef struct elt *Stack;
为什么在Stack之前有一个*它是什么意思?
我找到了指针的概念,特别是在难以掌握的函数的返回类型中。 提前谢谢。
答案 0 :(得分:5)
我可以理解大部分代码。但我无法绕过头脑 这部分是typedef struct elt * Stack;
那是使用typedef *。这只是意味着你写的时候
Stack x;
代码中的意味着:
struct elt * x;
但是如果你使用
Stack *s;
你的代码中的意味着:
struct elt ** s;
我找到了指针的概念,尤其是返回类型的指针 功能难以掌握。提前谢谢。
然后我建议你在继续使用该代码之前先了解指针和指针。
* 我认为C和C ++中的typedef存在一些细微差别:see here
答案 1 :(得分:1)
我找到了指针的概念,特别是在难以掌握的函数的返回类型中。提前谢谢。
这比这里可以涵盖的更多;找到一个好的教程(如果存在这样的事情)并从那里开始工作。但是,这里有一些事情需要记住:
*
运算符始终绑定到声明符,而不是类型说明符。例如,声明int* x, y, z;
被解析为int (*x), y, z;
IOW,只有x
被声明为指针。如果您想要将y
和z
声明为指针,则必须编写int *x, *y, *z;
*
和&
运算符的优先级低于[]
,()
和成员选择运算符等后缀运算符,因此:{{2 }}
T *x[N]; // declares x as an N-element array of pointers to T
T (*x)[N]; // declares x as a pointer to an N-element array of T
T *f(); // declares f as a function returning pointer to T
T (*f)(); // declares f as a pointer to a function returning T
*a.b == *(a.b) // dereferences a.b
*a->b == *(a->b) // dereferences a->b
&a.b == &(a.b) // takes the address of a.b
&a->b == &(a->b) // takes the address of a->b
a->b == (*a).b // dereferences a, then accesses b
的参数,如果您将其传递给int *
(或int **
,int (*)[N]
或{{1}类型,它会抱怨} {等等)int **
类型是一种“通用”指针类型,但你不能直接使用它(你不能取消引用float *
,也不能对它进行指针运算)。在C中,您可以将void *
值分配给任何指针对象,反之亦然,而无需使用强制转换; C ++需要对void *
指针类型转换进行强制转换。
void *
我们从地址all
中偏移a[i] == *(a + i);
个元素(非字节),并取消引用结果。但是,如果数组不是指针,这是如何工作的?
除非它是i
或一元a
运算符的操作数,或者是用于初始化声明中的另一个数组的字符串文字,否则类型为“N”的表达式 sizeof
“的元素数组将被转换(”衰减“)为”指向&
的指针“的表达式,表达式的值将是数组的第一个元素的地址。因此,当我们编写T
时,数组表达式T
将转换为指针类型,并从该指针偏移。请注意,对象 a[i]
未被转换;它始终是一个数组对象。