user-0 提问: 结构体 是属于声明，还是定义？

回复:
user: user-1
content: 引用 16 楼 Red_Stone 的回复:狭义上理解，变量定义是指声明并分配内存，变量声明是指为了调整作用域而做的引用因此编译器不会为变量声明做内存分配工作。 struct AAA {     int a； }； 这里可以认为是对struct AAA类型的定义，因此，可以如下声明或定义其变量： struct AAA aaa; 这句代码如果放在函数外边，即为全局定义（编译时分配内存），这时在其他文件中可以使用extern struct AAA aaa;来声明其为外部变量并引用； 如果放在函数内，就是自动变量的定义（编译时分配内存）。 分配内存的理解是错的。 比如typedef name的所谓定义就无所谓分配内存。 在C中实际上“定义”也就是“可能唯一”，这个概念充其量是习惯说法。 C++的定义和强制性的程序基本正确规则One Definition Rule相关，因此更加要命。 C在此对应的规则是： WG14/N1570 3 If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that: —a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type; —tags may be redeclared as specified in 6.7.2.3. 可以重复声明的就只有typedef name和tag。剩下的声明（注意不要求是定义）都没法在同一个作用域和名称空间内重复。 而C++不一样。 3.2 One definition rule [basic.def.odr] 1 No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template. （太长，下略。） 禁止重复的规则都是基于定义上的（同一个名称的不同声明出现冲突是另一回事），所以从普通的声明中区分出定义很重要。（另外C++没有name space，tag对应于class-name，在指定类型上是一回事。）

user: user-2
content: 引用 3 楼 supermegaboy 的回复:[quote=引用 楼主 missheaven2011 的回复:] 最近看书，声明可以需要用到的地方声明很多次，定义一个程序中只能有一次 那么 struct AAA {     int a； }； 这个结构体，在头文件中，被多个源文件调用，是不是说明这是对结构体类型的声明呢 有没有具体说明的相关文章  结构体属于类型定义，当它以不完整类型出现时，才属于类型声明。[/quote]++

user: user-3
content: 狭义上理解，变量定义是指声明并分配内存，变量声明是指为了调整作用域而做的引用因此编译器不会为变量声明做内存分配工作。 struct AAA {     int a； }； 这里可以认为是对struct AAA类型的定义，因此，可以如下声明或定义其变量： struct AAA aaa; 这句代码如果放在函数外边，即为全局定义（编译时分配内存），这时在其他文件中可以使用extern struct AAA aaa;来声明其为外部变量并引用； 如果放在函数内，就是自动变量的定义（编译时分配内存）。

user: user-4
content: 这个是结构体的定义，在使用时才需要声明结构体

user: user-5
content: 这是一个结构体的定义 一个结构体的声明可以如下: struct  sturct_name;

user: user-6
content: 个人意见：引用内容的长短不是最重要的，最重要的是看从哪里引用。 楼主的问题最该引用“C语法约定中的声明”，我承认我2楼错引了“C++语法约定中的声明” 10楼我纠正为“C语法约定中的声明”  谢谢FrankHB1989提醒。

user: user-1
content: 引用 9 楼 zhao4zhong1 的回复:[quote=引用 7 楼 FrankHB1989 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] C版哪来的class ？ 除了你没人提到class吧。 [/quote] 我是说2楼内容里面有class[/quote] 2楼不就是你引用的。 我说赵老湿以后要引用内容短点有针对性点行不，长了看得慌别人引用起来也累。

user: user-1
content: 引用 3 楼 supermegaboy 的回复:[quote=引用 楼主 missheaven2011 的回复:] 最近看书，声明可以需要用到的地方声明很多次，定义一个程序中只能有一次 那么 struct AAA {     int a； }； 这个结构体，在头文件中，被多个源文件调用，是不是说明这是对结构体类型的声明呢 有没有具体说明的相关文章  结构体属于类型定义，当它以不完整类型出现时，才属于类型声明。[/quote] 这个是错的。 C的“类型定义”专指typedef： WG14/N1570 6.7.8 Type definitions Syntax 1 typedef-name: identifier 这里只能说是带struct-or-union-specifier的tag declaration（struct-declaration有另外的含义）。 另外注意，“不完整类型”是一个已知类型自身的属性，不是决定声明或定义存在的理由。

user: user-6
content: 这个总该是纯C了吧： mk:@MSITStore:C:\MSDN98\98VS\2052\vclang.chm::/html/_clang_summary_of_declarations.htm Summary of Declarations declaration :  declaration-specifiers attribute-seq opt init-declarator-list opt ;                         /* attribute-seq is Microsoft Specific */  declaration-specifiers :  storage-class-specifier declaration-specifiers opt type-specifier declaration-specifiers opt type-qualifier declaration-specifiers opt  attribute-seq :            /* attribute-seq is Microsoft Specific */  attribute attribute-seq opt  attribute : one of      /* Microsoft Specific */  __asm __fastcall  __based __inline  __cdecl __stdcall    init-declarator-list :  init-declarator init-declarator-list , init-declarator  init-declarator :  declarator declarator = initializer /* For scalar initialization */  storage-class-specifier :  auto register static extern typedef __declspec ( extended-decl-modifier-seq ) /* Microsoft Specific */  type-specifier :  void char short int __int8       /* Microsoft Specific */ __int16      /* Microsoft Specific */ __int32      /* Microsoft Specific */ __int64      /* Microsoft Specific */ long float double signed unsigned struct-or-union-specifier enum-specifier typedef-name  type-qualifier :  const volatile  declarator :  pointer opt direct-declarator  direct-declarator :  identifier ( declarator ) direct-declarator [ constant-expression opt] direct-declarator ( parameter-type-list )   /* New-style declarator */ direct-declarator ( identifier-list opt )      /* Obsolete-style declarator */  pointer :  * type-qualifier-list opt * type-qualifier-list opt pointer  parameter-type-list :                           /* The parameter list */  parameter-list parameter-list , ...  parameter-list :  parameter-declaration parameter-list , parameter-declaration  type-qualifier-list :  type-qualifier type-qualifier-list type-qualifier  enum-specifier :  enum identifier opt { enumerator-list } enum identifier  enumerator-list :  enumerator enumerator-list , enumerator  enumerator :  enumeration-constant enumeration-constant = constant-expression  enumeration-constant :  identifier  struct-or-union-specifier :  struct-or-union identifier opt { struct-declaration-list } struct-or-union identifier  struct-or-union :  struct union  struct-declaration-list :  struct-declaration struct-declaration-list struct-declaration  struct-declaration :  specifier-qualifier-list struct-declarator-list ;  specifier-qualifier-list :  type-specifier specifier-qualifier-list opt type-qualifier specifier-qualifier-list opt  struct-declarator-list :  struct-declarator struct-declarator-list , struct-declarator  struct-declarator :  declarator type-specifier declarator opt : constant-expression  parameter-declaration :  declaration-specifiers declarator                /* Named declarator */ declaration-specifiers abstract-declarator opt /* Anonymous declarator */  identifier-list :      /* For old-style declarator */  identifier identifier-list , identifier  abstract-declarator :         /* Used with anonymous declarators */  pointer pointer opt direct-abstract-declarator  direct-abstract-declarator :  ( abstract-declarator ) direct-abstract-declarator opt [ constant-expression opt ] direct-abstract-declarator opt ( parameter-type-list opt )  initializer :  assignment-expression { initializer-list }   /* For aggregate initialization */  { initializer-list , }  initializer-list :  initializer initializer-list , initializer  type-name :  specifier-qualifier-list abstract-declarator opt  typedef-name :  identifier  extended-decl-modifier-seq :/*   Microsoft Specific */  extended-decl-modifier opt extended-decl-modifier-seq extended-decl-modifier  extended-decl-modifier :   /* Microsoft Specific */  thread naked dllimport dllexport

user: user-6
content: 引用 7 楼 FrankHB1989 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] C版哪来的class ？ 除了你没人提到class吧。 [/quote] 我是说2楼内容里面有class

user: user-1
content: 结构体类型。 结构体的tag是标识符，它可以被声明。 声明是一种语法构造。 WG14/N1570 6.7 Declarations Syntax 1 declaration: declaration-specifiers init-declarator-listopt ; static_assert-declaration declaration-specifiers: storage-class-specifier declaration-specifiers opt type-specifier declaration-specifiers opt type-qualifier declaration-specifiers opt function-specifier declaration-specifiers opt alignment-specifier declaration-specifiersopt init-declarator-list: init-declarator init-declarator-list ,init-declarator init-declarator: declarator declarator =initializer  LZ的代码是声明，规约为declaration-specifiers init-declarator-list ;，其中declaration-specifiers是type-specifier declaration-specifiers，这里type-specifier是struct-or-union-specifier。  定义是特殊的声明，满足以下语义构造： WG14/N1570 6.7/5 A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that: — for an object, causes storage to be reserved for that object; — for a function, includes the function body; —for an enumeration constant, is the (only) declaration of the identifier; — for a typedef name, is the first (or only) declaration of the identifier.  对于C++来说也类似，不过有两点显著差异： 声明引入名称(name) ，定义相对于名称（标识符的泛化），更强调相对于实体(entity) ； typedef只是声明不是定义。

user: user-1
content: 引用 5 楼 zhao4zhong1 的回复:C版哪来的class ？ 除了你没人提到class吧。

user: user-7
content: 定义，此struct的类型定义

user: user-6
content: C版哪来的class ？

user: user-1
content: 引用 2 楼 zhao4zhong1 的回复:Grammar of C++ Declarations declaration:   decl-specifiersopt declarator-listopt ; asm-declaration  function-definition  linkage-specification template-declaration:  asm-declaration:  __asm( string-literal );  decl-specifiers:   decl-specifiersopt decl-specifier  decl-specifier:  storage-class-specifier  type-specifier  fct-specifier  friend  typedef __declspec ( extended-decl-modifier-seq )  storage-class-specifier:   auto  register  static  extern  fct-specifier:   inline  virtual  type-specifier:   simple-type-name  class-specifier  enum-specifier  elaborated-type-specifier  const  volatile  extended-decl-modifier-seq:  extended-decl-modifieropt extended-decl-modifier extended-decl-modifier-seq  extended-decl-modifier:  thread naked dllimport dllexport  simple-type-name:   complete-class-name  qualified-type-name  char  short  int  long  signed  unsigned  float  double  void  elaborated-type-specifier:  class-key  identifier  class-key  class-name enum-name  class-key:   class  struct  union  qualified-type-name:   typedef-name  class-name :: qualified-type-name  complete-class-name:   qualified-class-name  :: qualified-class-name  qualified-class-name:   class-name  class-name :: qualified-class-name  enum-specifier:   enum identifieropt { enum-listopt }  enum-list:   enumerator  enum-list , enumerator  enumerator:   identifier  identifier = constant-expression  constant-expression:   conditional-expression  linkage-specification:   extern string-literal { declaration-listopt }  extern string-literal declaration  declaration-list:   declaration declaration-list  declaration  template-declaration:  template < template-argument-list > declaration  template-argument-list:  template-argument template-argument-list , template-argument  template-argument:  type-argument argument-declaration  type-argument:  class identifier  template-class-name:  template-name < template-arg-list >  template-arg-list:  template-arg template-arg-list , template-arg  template-arg:  expression type-name  original-namespace-name :  identifier  namespace-definition :  original-namespace-definition extension-namespace-definition unnamed-namespace-definition  original-namespace-definition :  namespace identifier { namespace-body }  extension-namespace-definition :  namespace original-namespace-name { namespace-body }  unnamed-namespace-definition :  namespace { namespace-body }  namespace-body :  declaration-seqopt  id-expression :  unqualified-id qualified-id  nested-name-specifier :  class-or-namespace-name :: nested-name-specifieropt   class-or-namespace-name :  class-name namespace-name  namespace-name :  original-namespace-name namespace-alias  namespace-alias :  identifier  namespace-alias-definition :  namespace identifier = qualified-namespace-specifier;  qualified-namespace-specifier :  ::opt nested-name-specifieropt class-or-namespace-name  using-declaration :  using ::opt nested-name-specifier unqualified-id using :: unqualified-id  using-directive :  using namespace ::opt nested-name-specifieropt namespace-name 赵老湿这里是C版，人家没问C艹。

user: user-8
content: 引用 11 楼 FrankHB1989 的回复:[quote=引用 3 楼 supermegaboy 的回复:] [quote=引用 楼主 missheaven2011 的回复:] 最近看书，声明可以需要用到的地方声明很多次，定义一个程序中只能有一次 那么 struct AAA {     int a； }； 这个结构体，在头文件中，被多个源文件调用，是不是说明这是对结构体类型的声明呢 有没有具体说明的相关文章  结构体属于类型定义，当它以不完整类型出现时，才属于类型声明。[/quote] 这个是错的。 C的“类型定义”专指typedef： WG14/N1570 6.7.8 Type definitions Syntax 1 typedef-name: identifier 这里只能说是带struct-or-union-specifier的tag declaration（struct-declaration有另外的含义）。 另外注意，“不完整类型”是一个已知类型自身的属性，不是决定声明或定义存在的理由。  [/quote]  你过虑了，偶说的类型定义显然不可能是typedef。

user: user-9
content: 看来,楼主的头脑中没有内部连接和外部连接的概念呀!!! 现在在给你科普一下... 时刻要注意区分内部连接和外部连接   以下情况有内部连接: 　　 　　a)所有的声明 　　 　　b)名字空间(包括全局名字空间)中的静态自由函数、静态友元函数、静态变量的定义 　　 　　c)enum定义 　　 　　d)inline函数定义(包括自由函数和非自由函数) 　　 　　e)类的定义,当然也包括struct定义了　 　　f)名字空间中const常量定义 　　 　　g)union的定义 　　 　　外部连接:在一个多文件程序中，假如一个名称在连接时可以和其它编译单元交互，那么这个名称就有外部连接。 　　 　　以下情况有外部连接: 　　 　　a)类非inline函数总有外部连接。包括类成员函数和类静态成员函数 　　 　　b)类静态成员变量总有外部连接。 　　 　　c)名字空间(包括全局名字空间)中非静态自由函数、非静态友元函数及非静态变量

user: user-10
content: 我觉得这是引用该结构体的定义，如果多个.h文件都include了包含这段代码的.h文件(并且出现嵌套的话)，

user: user-10
content: struct AAA {     int a； }； 这应该是定义一个名为“AAA”的结构体。  “在头文件中，被多个源文件调用，是不是说明这是对结构体类型的声明呢？” 我觉得这是引用该结构体的定义，如果多个.h文件都include了包含这段代码的.h文件的话， 编译的时候是会提示错误的“类型重定义”。  而真正要用到“AAA”这个结构体的时候， struct AAA a = { 123 }; struct AAA b = { 456 }; 这才是声明一个名称为“a”的AAA类型的结构体变量；

user: user-1
content: C的tag和对应类型声明的关系： WG14/N570 6.7.2.3 4 All declarations of structure, union, or enumerated types that have the same scope and use the same tag declare the same type. Irrespective of whether there is a tag or what other declarations of the type are in the same translation unit, the type is incomplete until immediately after the closing brace of the list defining the content, and complete thereafter. 至于说不指定{...}的形式嘛…… WG14/N1570 6.7.2.3 7 A declaration of the form struct-or-union identifier ; specifies a structure or union type and declares the identifier as a tag of that type. 8 If a type specifier of the form struct-or-union identifier occurs other than as part of one of the above forms, and no other declaration of the identifier as a tag is visible, then it declares an incomplete structure or union type, and declares the identifier as the tag of that type. 可见类似LZ的代码声明了类型struct AAA；而struct AAA;在之前没有可见的上述形式的声明时声明不完整类型struct AAA。 按C的说法，两者都只是声明而不是定义。（顺便，前者在C++是类定义；后者是类名声明，不是定义。）当然，{}里的内容可以是定义。