【问题标题】:typedef struct elt *Stack; why is there a * heretypedef struct elt *Stack;为什么这里有*
【发布时间】:2016-06-30 17:15:13
【问题描述】:

这是使用链表实现堆栈的完整代码。它来自 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 前面有一个 * 是什么意思?

我正在寻找指针的概念,尤其是在难以掌握的函数返回类型方面。 提前致谢。

【问题讨论】:

  • 这不是一个辅导网站。指针的概念非常广泛,应该使用专门的资源进行研究。
  • 这是C 代码,而不是 C++。这一行:e = malloc(sizeof(struct elt)); 不会编译为 C++。
  • @PaulMcKenzie:代码中的什么阻止了代码被编译为 C++?
  • @ThomasMatthews malloc 的返回值没有被强制转换。 C++ 需要强制转换。
  • @PaulMcKenzie 我知道它是 C。我标记了两者,因为两者相似。我的错。

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


【解决方案1】:

我能理解大部分代码。但我无法绕开我的头 这部分 typedef struct elt *Stack;

那是使用 typedef*。这只是意味着当你写作时

Stack x;

在您的代码中意味着:

struct elt * x;

如果你使用

Stack *s;

在您的代码中意味着:

struct elt ** s;

我正在寻找指针的概念,尤其是在返回类型中 功能难以掌握。提前致谢。

那么我建议您在继续编写该代码之前先了解指针和指向指针的指针。


*我认为 C 和 C++ 中的 typedef 存在一些细微差别:see here

【讨论】:

  • 谢谢伙计。你能告诉我 int *foo 和 int *(foo) 之间是否有区别吗?
  • @user3600999 foo 是不是一个变量?不应该没有:ideone.com/mgjfPW
  • 没有。一个函数。抱歉,我不是很清楚。顺便说一句,他为什么在 StackPush 和其他函数中使用struct elt *e; 而不是只使用Stack e
  • @user3600999 他只是为了舒适而减少输入**星。您需要显示这些函数定义的完整代码 sn-p
【解决方案2】:

我正在寻找指针的概念,尤其是在难以掌握的函数返回类型方面。提前致谢。

这比这里可以涵盖的要多一些;为自己找到一个很好的教程(如果存在这样的东西)并从那里开始工作。但是,请记住以下几点:

  • 在指针声明中,* 运算符始终绑定到 声明符,而不是类型说明符。例如声明
    int* x, y, z;
    解析
    int (*x), y, z;
    IOW,只有x 被声明为指针。如果您还想将yz 声明为指针,则必须编写
    int *x, *y, *z;
    
  • 一元*&amp; 运算符的优先级低于[]() 等后缀运算符和成员选择运算符,因此:
    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],或 int **,或 float * 等),它会报错。 void * 类型是“通用”指针类型,但不能直接使用它(不能取消引用 void *,也不能对其进行指针运算)。在 C 中,您可以将 void * 值分配给任何指针对象,反之亦然,无需强制转换; C++ 需要对all 指针类型转换进行强制转换。
  • 数组不是指针。数组下标操作是用指针算法定义的:
    a[i] == *(a + i);
    
    我们从地址a 偏移i 元素(不是字节)并取消引用结果。但是,如果数组不是指针,这是如何工作的? 除非它是 sizeof 或一元 &amp; 运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则 表达式 类型为“@ 的 N 元素数组” 987654347@" 将被转换(“衰减”)为类型为“指向T”的表达式,表达式的值将是数组第一个元素的地址。因此,当我们编写a[i] 时,数组表达式a 被转换为指针类型,并且我们从该指针偏移。注意 object a 没有被转换;它始终是一个数组对象。

【讨论】:

    猜你喜欢
    • 2016-06-04
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 2011-06-18
    • 2017-10-04
    相关资源
    最近更新 更多