这个类型结构定义的指针是什么意思(在 C 中)?

What does this pointer of type structure definition mean (in C)?

在K&R Chapter 6中,声明如下:

struct{
    int len;
    char *str;
} *p;

我不明白这个指针 p 指向哪个结构,也不知道这样的指针定义是否有效,因为在书中给出的所有其他示例以及我在其他地方看到的示例中,当定义指向 a 的指针时structure,结构的名字,也就是需要被定义的类型。例如,

struct example{
    int a;
    ...
}s1;

然后,

struct example *ptr = &s1;

因此,提到 ptr 指向类型结构示例而不仅仅是结构。

另外,特别感兴趣的是:

*p->str fetches whatever str points to; *p->str++ increments str after accessing whatever it points to (just like *s++);

我一开始无法理解 p 是什么,因此也无法理解递增和取消引用。

这是怎么回事?

提前致谢!

P.S。我是新来的,所以任何关于问题格式的反馈也将不胜感激。

struct 关键字的工作方式有点像 typedef 的扩展版本,只是您创建了一个复杂的自定义类型(称为结构)而不是为现有类型设置别名。如果只有一个东西需要使用声明的类型,则不需要为该类型提供显式名称。

您正在查看的第一个语句声明了一个具有两个字段的结构,但没有命名它。这称为匿名结构。但是,该声明确实提供了该类型的指针。

一种可能的 use-case 这种声明是当你为外部库创建 header 时,可能甚至不是用 C 编写的。在这种情况下,结构的类型可能不透明或不完整,您只需要方便地参考其中的某些部分。使结构匿名可以防止您自己轻松分配它,但允许您通过指针与它交互。

更常见的是,您会看到此表示法与命名结构或至少是别名结构结合使用。第二条语句可以重写为

struct example { ... } s1, *ptr;

在这种情况下,struct example *ptr = &s1; 将只是 ptr = &s1;

更常见的情况是使用带有 typedef 的匿名结构,创建不包含 struct 关键字的自定义类型名称。你的第二个例子可以改写为

typedef struct { ... } example, *pexample;
example s1;
pexample ptr; // alternatively example *ptr;
ptr = &s1;

请注意,s1 的类型是 example 而不是 struct example

(匿名结构的)另一种用途是在联合或其他结构中使用它们,这基本上将该结构的使用限制在特定的父联合或结构中,而不是其他任何东西,这从程序员的角度来看非常有用视图,因为查看这样的代码它为我们提供了它在其内部结构或联合的上下文中本地使用的信息 - 仅此而已。 (也使我们免于命名)。


此外,如果您使用此匿名结构,您将无法分配它的一个实例,而不是已经存在的实例。

示例:-(stark 的评论:如何使用它?)

struct {
  int a;
  int b;
} p;

scanf("%d",&p.a);

如果您需要一个临时的、一次性使用的结构(或联合)定义,而该结构(或联合)在声明它的范围之外将无用,您可以使用所谓的 anonymous or unnamed structs and unions. This saves you from having to declare the struct before you use it and, in the case of complex types, declaring the inner types, such as here.

对于初学者,请考虑以下简单程序

#include <stdlib.h>
#include <stdio.h>
#include <string.h> 

int main(void) 
{
    struct {
        int len;
        char *str;
    } *p;

    p = malloc( sizeof( *p ) );

    p->str = "Hello Nihal Jain";
    p->len = strlen( p->str );

    while ( *p->str ) putchar( *p->str++ );
    putchar( '\n' );

    free( p );

    return 0;
}

它的输出是

Hello Nihal Jain

所以在这个声明中

    struct {
        int len;
        char *str;
    } *p;

声明了一个未命名结构类型的指针。指针本身未初始化。你可以这样写

    struct {
        int len;
        char *str;
    } *p = malloc( sizeof( *p ) );

对于这个简单的程序,不需要结构的名称,因为程序中既不存在也不需要结构类型的对象声明。

因此您不能声明结构类型的对象,但在这种情况下不需要。

根据 C 标准,结构或联合声明如下

struct-or-union-specifier:
    struct-or-union identifieropt { struct-declaration-list }
    struct-or-union identifier

可见如果有struct-declaration-list,标识符是可选的。所以一个未命名的结构可以用作类型说明符。

再举一个使用枚举的例子。您可以在不声明枚举类型的情况下声明枚举数。例如

enum { EXIT_SUCCESS = 0, EXIT_FAILURE = -1 }; 

如果程序中没有这样的要求,您可以使用具有int类型的枚举器而无需声明枚举类型的对象。