结构声明不足够?

huangapple go评论60阅读模式
英文:

Struct declaration NOT sufficient?

问题

以下是翻译好的部分:

在以下的C代码中:

struct Point2_s;
struct Point1_s{
  int x;
  int y;
  Point2_s P2;
} Point1;

struct Point2_s{
  int x;
  int y;
} ;


int main() {
    ...
    return 0;
}

我得到了一个错误:

未知类型名‘Point2_s’

有人能解释为什么它不工作吗?为什么在定义Point1_s成员P2Point2_s结构体的声明不足呢?

英文:

Having the following C code:

struct Point2_s;
struct Point1_s{
  int x;
  int y;
  Point2_s P2;
} Point1;

struct Point2_s{
  int x;
  int y;
} ;


int main() {
    ...
    return 0;
}

I'm getting an error:

> unknown type name ‘Point2_s’

Can anyone can please explain me WHY it doesn't work? Why doesn't the struct Point2_s declaration is insufficient when defining the Point1_s member P2?

答案1

得分: 2

在这行中,声明了一个不完整的结构体指定符 struct Point2_s

在这个声明中,使用了一个未知的名称 Point2_s。它与 struct Point2_s 不同。

但即使你写成:

struct Point1_s{
  int x;
  int y;
  struct Point2_s P2;
} Point1;

你仍然不能在数据成员声明中使用不完整的类型。

根据C标准(6.7.2.1 结构和联合体指定符):

3 结构体或联合体不得包含不完整或函数类型的成员(因此,结构体不得包含自身的实例,但可以包含指向自身实例的指针),除非具有多个命名成员的结构体的最后一个成员具有不完整的数组类型;这样的结构体(以及包含该结构体成员的任何联合体,可能递归地包含该结构体成员)不得作为结构体的成员或数组的元素。

因此,你需要这样写:

struct Point2_s{
  int x;
  int y;
} ;

struct Point1_s{
  int x;
  int y;
  struct Point2_s P2;
} Point1;

或者你可以这样写:

typedef struct Point2_s{
  int x;
  int y;
} Point2_s;

struct Point1_s{
  int x;
  int y;
  Point2_s P2;
} Point1;

在这种情况下,名称 Point2_s 是类型说明符 struct Point2_s 的别名。

另一方面,正如其他回答中指出的,你可以使用不完整类型的指针,因为指针本身始终是完整类型。也就是说,你可以这样写:

struct Point2_s;
struct Point1_s{
  int x;
  int y;
  struct Point2_s *P2;
} Point1;
英文:

In this line

struct Point2_s;

there is declared an incomplete structure specifier struct Point2_s.

In this declaration

struct Point1_s{
  int x;
  int y;
  Point2_s P2;
} Point1;

there is used an unknown name Point2_s. It is not the same as struct Point2_s.

But even if you will write

struct Point1_s{
  int x;
  int y;
  struct Point2_s P2;
} Point1;

nevertheless you may not use an incomplete type in a data member declaration.

From the C Standard (6.7.2.1 Structure and union specifiers)

> 3 A structure or union shall not contain a member with incomplete or
> function type
(hence, a structure shall not contain an instance of
> itself, but may contain a pointer to an instance of itself), except
> that the last member of a structure with more than one named member
> may have incomplete array type; such a structure (and any union
> containing, possibly recursively, a member that is such a structure)
> shall not be a member of a structure or an element of an array.

Instead you need to write

struct Point2_s{
  int x;
  int y;
} ;

struct Point1_s{
  int x;
  int y;
  struct Point2_s P2;
} Point1;

Or you could write

typedef struct Point2_s{
  int x;
  int y;
} Point2_s;

struct Point1_s{
  int x;
  int y;
  Point2_s P2;
} Point1;

In this case the name Point2_s is an alias for the type specifier struct Point2_s.

On the other hand, as it is pointed out in other answers you may use pointers to incomplete types because pointers themselves are always complete types. That is you may write

struct Point2_s;
struct Point1_s{
  int x;
  int y;
  struct Point2_s *P2;
} Point1;

答案2

得分: 2

前向声明仅用于声明前向声明的结构体的指针。但它不知道结构的大小,因此不能直接使用该类型(它如何知道为 P2 成员保留多少空间?)。

只需颠倒声明的顺序:

struct Point2_s{
  int x;
  int y;
};

struct Point1_s{
  int x;
  int y;
  struct Point2_s P2;  // 没有使用 typedef,所以按照 C 标准,需要使用 struct 声明成员
} Point1;

或者你需要使用指针:

struct Point2_s;
struct Point1_s{
  int x;
  int y;
  struct Point2_s *P2; // 指针,再次添加 struct;P2 需要单独分配空间,例如使用 malloc
} Point1;

struct Point2_s{
  int x;
  int y;
};
英文:

A forward declaration can only be used to declare pointers to the forward-declared struct. It doesn't know how big it is though, so it can't use the type directly (how does it know how much space to reserve for the P2 member?).

Just reverse the order of declaration:

struct Point2_s{
  int x;
  int y;
};

struct Point1_s{
  int x;
  int y;
  struct Point2_s P2;  // You didn't typedef, so by the C standard, you need struct to declare the member
} Point1;

or you'll need to use pointers:

struct Point2_s;
struct Point1_s{
  int x;
  int y;
  struct Point2_s *P2; // Pointer, again adding struct; P2 will need to be allocated separately, e.g. by malloc
} Point1;

struct Point2_s{
  int x;
  int y;
};

答案3

得分: 0

前向声明在这种情况下不起作用(抽象出缺少的“struct”),因为编译器需要知道成员“P2”的大小。您需要在使用它的声明之前进行声明。

struct Point2_s{
  int x;
  int y;
} ;

struct Point1_s{
  int x;
  int y;
  struct Point2_s P2;
} Point1;

前向声明仅适用于指针:

struct Point2_s;

struct Point1_s{
  int x;
  int y;
  struct Point2_s *P2;
} Point1;

struct Point2_s{
  int x;
  int y;
} ;
英文:

Forward declaration will not work in this case (abstracting from missing struct) as compiler needs to know the size of the member P2. You need to declare it before the the declaration which uses it.

struct Point2_s{
  int x;
  int y;
} ;

struct Point1_s{
  int x;
  int y;
  struct Point2_s P2;
} Point1;

Forward declaration will only work only for pointers:

struct Point2_s;

struct Point1_s{
  int x;
  int y;
  struct Point2_s *P2;
} Point1;

struct Point2_s{
  int x;
  int y;
} ;

huangapple
  • 本文由 发表于 2023年2月10日 07:15:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75405436.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定