在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。我是新来的,所以对此问题格式的任何反馈也将不胜感激。
答案 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。