typedef struct elt * Stack;为什么这里有*

时间:2016-06-30 17:15:13

标签: c++ c pointers data-structures stack

这是使用链接列表的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之前有一个*它是什么意思?

我找到了指针的概念,特别是在难以掌握的函数的返回类型中。 提前谢谢。

2 个答案:

答案 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被声明为指针。如果您想要将yz声明为指针,则必须编写
    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 *指针类型转换进行强制转换。
  • ARRAYS不是指针 。数组下标操作是根据指针算法定义的:
    void *
    我们从地址all中偏移a[i] == *(a + i); 个元素(非字节),并取消引用结果。但是,如果数组不是指针,这是如何工作的? 除非它是i或一元a运算符的操作数,或者是用于初始化声明中的另一个数组的字符串文字,否则类型为“N”的表达式 sizeof“的元素数组将被转换(”衰减“)为”指向&的指针“的表达式,表达式的值将是数组的第一个元素的地址。因此,当我们编写T时,数组表达式T将转换为指针类型,并从该指针偏移。请注意,对象 a[i]未被转换;它始终是一个数组对象。