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

时间:2017-11-01 19:01:07

标签: c pointers structure dereference anonymous-struct

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

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

我无法理解这个指针p指向哪个结构,如果这样的指针定义甚至是有效的,因为在书中给出的所有其他示例和我看到的其他示例中,在定义指向结构的指针时,需要提及结构的名称,即要定义的类型。例如,

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

然后,

struct example *ptr = &s1;

所以,提到ptr指向一个类型结构示例而不仅仅是struct。

另外,特别感兴趣的是:

  

* p-> str获取任何str点; *对 - > STR ++   在访问它指向的任何内容后递增str(就像* s ++);

我无法首先遵循p是什么,因此,不是增量和解除引用。

这里发生了什么?

提前致谢!

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

4 个答案:

答案 0 :(得分:13)

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

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

这种声明的一个可能用例是当您为外部库创建一个标头时,可能是一个甚至没有用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

答案 1 :(得分:3)

首先考虑以下简单程序

#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的枚举器而不声明枚举类型的对象。

答案 2 :(得分:2)

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

此外,如果您使用此匿名结构,您将无法分配除已存在的实例之外的其中一个实例。

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

struct {
  int a;
  int b;
} p;

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

答案 3 :(得分:0)

如果您需要一个特定的,一次性使用的结构(或联合)定义,它在声明它的范围之外没有用处,那么您将使用所谓的anonymous or unnamed structs and unions。这使您不必在使用之前声明结构,并且在复杂类型的情况下,声明内部类型,例如here