typedef structelt*Stack;为什么这里有一个*

typedef struct elt *Stack; why is there a * here

本文关键字:这里 有一个 为什么 Stack structelt typedef      更新时间:2023-10-16

这是使用链表实现Stack的完整代码。这是詹姆斯·阿斯普内斯为耶鲁大学撰写的数据结构笔记(有什么好的吗?(

#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 %dn", i);
        stackPush(&s, i);
        stackPrint(&s);
    }
    while(!stackEmpty(&s)) {
        printf("pop gets %dn", stackPop(&s));
        stackPrint(&s);
    }
    return 0;
}

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

为什么Stack前面有一个*,它是什么意思?

我发现指针的概念很难理解,尤其是在函数的返回类型中。提前谢谢。

我能理解大部分代码。但我无法理解本部分typedef structelt*Stack;

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

Stack x;

在你的代码中,它的意思是:

struct elt * x;

但是,如果您使用

Stack *s;

在您的代码中,它将意味着:

struct elt ** s;

我发现了指针的概念,尤其是在功能难以掌握。提前谢谢。

然后,我建议您在继续使用该代码之前,先了解指针和指向指针的指针。


*我认为C和C++中的typedef有一些细微的区别:请参阅此处

我发现指针的概念很难理解,尤其是在函数的返回类型中。提前谢谢。

这比这里所能涵盖的要多一些;给自己找一个好的教程(如果存在这样的东西的话(,然后从那里开始工作。然而,这里有一些事情需要记住:

  • 在指针声明中,*运算符始终绑定到声明符,而不是类型说明符。例如,声明
    int* x, y, z;
    解析为
    int (*x), y, z;
    IOW,只有x被声明为指针。如果您也想将yz声明为指针,则必须编写
    int *x, *y, *z;
    
  • 一元*&运算符的优先级低于后缀运算符(如[]()和成员选择运算符(,因此:
    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或一元&运算符的操作数,或者是用于初始化声明中另一个数组的字符串文字,否则类型为"T的N元素数组"的表达式将被转换("decay"(为类型为"指向T的指针"的表达式,并且表达式的值将是数组第一个元素的地址。因此,当我们写入a[i]时,数组表达式a被转换为指针类型,并且我们从该指针偏移。请注意,对象a未被转换;它始终是一个数组对象。
相关文章: