请问C标准认为有一两个'结构uperms_entry“类型这个头? [英] Does the C standard consider that there are one or two 'struct uperms_entry' types in this header?

查看:90
本文介绍了请问C标准认为有一两个'结构uperms_entry“类型这个头?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您能否给引经据典从的三C标准之一(preferably C99或C11),表示下面的头文件是否有一个或两个结构uperms_entry 在这类型的?

Can you give chapter and verse from one of the three C standards (preferably C99 or C11) which indicates whether the following header file has one or two struct uperms_entry types in it?

#ifndef UPERMS_CACHE_INCLUDE
#define UPERMS_CACHE_INCLUDE

typedef struct mutex MT_MUTEX;

typedef struct uperms_cache
{
    MT_MUTEX            *cache_lock;
    int                  processing;
    struct uperms_entry *uperms_list;  // No prior struct uperms_entry
} uperms_cache_t;

typedef struct uperms_entry // Does this define a different struct uperms_entry?
{
    char                 username[32];
    int                  perms;
    struct uperms_entry *next;
} uperms_entry_t;

#endif /* UPERMS_CACHE_INCLUDE */

兼职问题:


  1. 如果有两种类型,有没有什么办法让GCC报告问题?

  2. 如果有两种类型,它常是在实践中?

(我认为答案是'是 - 严格有两种类型',然后(1)不和(2)否)。

(I think the answers are 'yes — strictly there are two types', and then (1) No and (2) No.)

上下文:内部code回顾 - 我想扭转结构的顺序,但我不知道我是否被完全过于迂腐

更新:

显然,答案的最初的问题是'有一个结构uperms_entry ,因此问题编号为1和2是没有实际意义。我很高兴我在code检讨抛出一个合适的嘘声前检查。

Clearly, the answer to the initial question is 'there is one struct uperms_entry' and therefore the questions numbered 1 and 2 are moot. I'm glad I checked before throwing a hissy fit in a code review.

本节加入长的首要问题得到解决之后。

This section was added long after the primary question was resolved.

下面是从ISO / IEC一些广泛但相关报价9899:2011:

Here are some extensive but relevant quotes from ISO/IEC 9899:2011:

¶1两种类型具有兼容的类型,如果其类型是相同的。
  确定附加规则两种类型是否兼容是
  6.7.2类型说明符类型修饰符描述的,在6.7.3,
  在6.7.6的说明符。 55)此外,二元结构,
  在不同的翻译单位工会申报,或枚举类型
  兼容,如果他们的标签和成员符合下列要求:
  如果一个与标签声明,其它应用相同的声明
  标签。如果两者都各自翻译中的任何位置完成
  单位,那么以下额外要求:应当有
  他们的成员之间的一对一的对应关系,使得每对
  相应的成员宣称与兼容的类型;如果一个成员
  的一对与一个取向限定声明,另一种是
  与同等定位符声明;并且如果一个成员
  这对声明了一个名字,另一种是声明的同
  名称。对于两种结构,相应的成员应声明
  相同的顺序。对于两种结构或联合,相应的位字段
  应具有相同的宽度。对于两个枚举,相应的成员
  应具有相同的值。

§6.2.7 Compatible type and composite type

¶1 Two types have compatible type if their types are the same. Additional rules for determining whether two types are compatible are described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.6 for declarators.55) Moreover, two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are completed anywhere within their respective translation units, then the following additional requirements apply: there shall be a one-to-one correspondence between their members such that each pair of corresponding members are declared with compatible types; if one member of the pair is declared with an alignment specifier, the other is declared with an equivalent alignment specifier; and if one member of the pair is declared with a name, the other is declared with the same name. For two structures, corresponding members shall be declared in the same order. For two structures or unions, corresponding bit-fields shall have the same widths. For two enumerations, corresponding members shall have the same values.

55)两种类型不需要相同是兼容的

55) Two types need not be identical to be compatible.

¶8在一个struct声明列表的presence
  结构-或工会说明符声明了一个新的类型,翻译中
  单元。该结构声明列表是声明的序列
  结构或联合的成员。如果结构声明列表呢
  不含任何名称的成员,无论是直接或经由一个匿名
  结构或匿名联合的行为是不确定的。类型是
  不完整的,直到后,立即} 终止列表,
  此后完成。

¶8 The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit. The struct-declaration-list is a sequence of declarations for the members of the structure or union. If the struct-declaration-list does not contain any named members, either directly or via an anonymous structure or anonymous union, the behavior is undefined. The type is incomplete until immediately after the } that terminates the list, and complete thereafter.

¶4结构,联合或枚举类型的所有声明有
  相同的范围,并使用相同的标签声明相同的类型。不管
  是否存在一个标记或在什么其他声明的类型的
  同样的翻译单元,类型是不完整的 129)直到
  后马上列表定义内容的右大括号,
  此后完整。

¶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 incomplete129) until immediately after the closing brace of the list defining the content, and complete thereafter.

¶5结构,联合的两个声明或枚举类型有哪些
  在不同的范围,或者使用不同的标签声明不同的类型。每
  结构,联合的声明,或枚举类型,不
  包括:电子标签声明了一个独特的类型。

¶5 Two declarations of structure, union, or enumerated types which are in different scopes or use different tags declare distinct types. Each declaration of a structure, union, or enumerated type which does not include a tag declares a distinct type.

¶6形式的类型说明符

结构-或工会的标识符 <子>选择 {结构声明列表}

枚举标识符 <子>选择 {枚举列表}

枚举标识符 <子>选择 {枚举列表,}

声明结构,联合或枚举类型。该列表定义
  结构的内容,工会的内容,或枚举的内容。如果
  提供标识, 130)类型说明符还声明
  该标识符是该类型的标签

declares a structure, union, or enumerated type. The list defines the structure content, union content, or enumeration content. If an identifier is provided,130) the type specifier also declares the identifier to be the tag of that type.

¶7形式的声明

struct-or-union identifier ;


  
  

指定一个结构或联合类型,并声明标识符作为
  该类型的标签。 131)

¶8如果窗体的类型说明符

¶8 If a type specifier of the form

struct-or-union identifier


  
  

发生其他不是作为上述形式之一的一部分,并没有其他
  标识符作为标签的声明是可见的,那么它的声明
  不完全结构或联合类型,并声明标识符作为
  该类型的标签。 131)

¶9如果窗体的类型说明符

¶9 If a type specifier of the form

struct-or-union identifier

enum identifier


  
  

发生其他不是作为上述形式之一的一部分,并声明
  的标识符作为一个标记是可见的,则它指定的相同类型
  如其他申报,并且不重新声明标签。

occurs other than as part of one of the above forms, and a declaration of the identifier as a tag is visible, then it specifies the same type as that other declaration, and does not redeclare the tag.

¶12例2来说明使用标签之前声明
  指定一对相互引用的结构中,声明

¶12 EXAMPLE 2 To illustrate the use of prior declaration of a tag to specify a pair of mutually referential structures, the declarations

struct s1 { struct s2 *s2p; /* ... */ }; // D1
struct s2 { struct s1 *s1p; /* ... */ }; // D2


  
  

指定一对包含指向彼此结构。
  但是请注意,如果S2已经被定义为在一个标签
  封闭范围,申报D1会提到它,而不是标签
  S2在D2声明。为了消除这种情况下的灵敏度,该
  声明

specify a pair of structures that contain pointers to each other. Note, however, that if s2 were already declared as a tag in an enclosing scope, the declaration D1 would refer to it, not to the tag s2 declared in D2. To eliminate this context sensitivity, the declaration

struct s2;


  
  

可以先D1的插入。该声明在内部一个新的标签S2
  范围;声明D2即可完成新型的规格。

may be inserted ahead of D1. This declares a new tag s2 in the inner scope; the declaration D2 then completes the specification of the new type.

129)只能由使用的不完全类型时的大小
  无需该类型的一个对象。它是不需要的,例如,
  当一个typedef名被宣布为一个结构的说明或
  工会,或当指针或函数返回结构或联合
  正在申报。 (参见不完全类型6.2.5。)规格
  这样的功能被调用或定义之前已完全。

129) An incomplete type may only by used when the size of an object of that type is not needed. It is not needed, for example, when a typedef name is declared to be a specifier for a structure or union, or when a pointer to or a function returning a structure or union is being declared. (See incomplete types in 6.2.5.) The specification has to be complete before such a function is called or defined.

130)功能如果没有标识符,类型可以,内
  翻译单元,仅由它是声明被称为
  的一部分。当然,当该声明是一个类型名字,
  随后的声明可以使用该typedef名称的声明
  具有特定结构,联合或枚举类型的对象。

130) If there is no identifier, the type can, within the translation unit, only be referred to by the declaration of which it is a part. Of course, when the declaration is of a typedef name, subsequent declarations can make use of that typedef name to declare objects having the specified structure, union, or enumerated type.

131)类似的建设与枚举不存在。

131) A similar construction with enum does not exist.

¶10对于两个限定类型是兼容的,两者应具有
  兼容型相同的合格版本;的顺序
  符或预选赛没有列表内输入预选赛
  影响指定的类型。

¶10 For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.

在§6.7.6的讨论涉及的指针,数组和功能
声明符并不会真正影响结构或联合。

我意识到例2的时候我写了这个问题。这是一些
大声思考了一些什么手段以上的信息。

I was aware of Example 2 when I wrote the question. This is some thinking out loud about some of what the information above means.

考虑这个例子,它编译干净:

Consider this example, which compiles cleanly:

#include <stdio.h>
struct r1 { int x; };

struct r1;

struct r1 p0;

//struct r1 { int y; };     // Redefinition of struct r1

extern void z(void);

void z(void)
{
    struct r1 p1 = { 23 };
    struct r1;
    //struct r1 p2;         // Storage size of p2 is not known
    struct r2 { struct r1 *rn; int y; };
    struct r1 { struct r2 *rn; int z; };
    struct r2 p = { 0, 1 };
    struct r1 q = { &p, 2 };
    p.rn = &q;
    printf("p.y = %d, q.z = %d\n", p.y, q.z);
    printf("p1.x = %d\n", p1.x);
}

的函数示出了当实施例2适用,但并不明智
code。 P1 在函数的声明将是一个结构
的相同类型的全局变量 P0 。即使它的类型名称
结构R1 ,这是一个不同的(不兼容)从类型的
类型局部变量 P

The function illustrates when Example 2 applies, but is not sensible code. The declaration of p1 in the function is would be a structure of the same type as the global variable p0. Even though its type name is struct r1, it is of a different (and incompatible) type from the type of the local variable p.

结构R1 的在全球范围内重新定义是不允许的,
无论元素是否被命名为 X 。现有
结构R1; 是一个无操作在这种情况下

The redefinition of struct r1 at the global level is not allowed, regardless of whether the element is named x or y. The prior struct r1; is a no-op in this context.

一个有趣的问题是可以起到以Z 通过 P 其他任何
功能(称之为 A )?答案是一个合格的是,以及一些
约束是有趣。 (这也将是惨不忍睹编码
风格的尝试,近乎疯狂的)。这个函数必须存在于
单独的翻译单元(TU)。该函数声明必须是内部
功能以Z (因为如果它的功能外,它的原型必须
请参阅结构R1 函数外定义,而不是结构
R1
中定义。

One interesting issue is 'can function z pass p or q to any other function (call it a)? The answer is a qualified 'yes', and some of the constraints are interesting. (It would also be appalling coding style to try it, verging on the insane.) The function must exist in a separate translation unit (TU). The function declaration must be inside function z (because if it is outside the function, its prototype must refer to the struct r1 defined outside the function, not the struct r1 defined inside.

在对方恩,一定程度的理智必须prevail:函数 A 必须
有兼容的结构类型结构R1 结构R2 可见
在其全球范围。

In the other TU, a degree of sanity must prevail: the function a must have the compatible structure types struct r1 and struct r2 visible in its global scope.

下面是另外一个例子,但是这个不能编译:

Here's another example, but this one does not compile:

#include <stdio.h>

struct r1;
extern void z(struct r1 *r1p);
extern void y(struct r1 *r1p);

void y(struct r1 *r1p)
{
    struct r2 { struct r1 *rn; int y; };
    struct r1 { struct r2 *rn; int z; };
    struct r2 p = { r1p, 1 };
    struct r1 q = { &p, 2 };
    p.rn = &q;
    printf("p.y = %d, q.z = %d\n", p.y, q.z);
}

void z(struct r1 *r1p)
{
    struct r1
    struct r2 { struct r1 *rn; int y; };
    struct r1 { struct r2 *rn; int z; };
    struct r2 p = { r1p, 1 };
    struct r1 q = { &p, 2 };
    p.rn = &q;
    printf("p.y = %d, q.z = %d\n", p.y, q.z);
}

从GCC 4.7.1在Mac OS X 10.7.4的警告是:

The warnings from GCC 4.7.1 on Mac OS X 10.7.4 are:

structs3.c: In function 'y':
structs3.c:13:10: warning: assignment from incompatible pointer type [enabled by default]
structs3.c: In function 'z':
structs3.c:22:12: warning: initialization from incompatible pointer type [enabled by default]
structs3.c:22:12: warning: (near initialization for 'p.rn') [enabled by default]

第13行是赋值 p.rn =安培;问; 函数和第23行是
试图定义和功能初始化结构R2 P 以Z

这表明,职能范围内,结构的 RN 元素
R2
是一个指向不完全类型结构R1 的声明
全局范围。添加结构R1; 为code的第一线内
功能将允许code编译,但初始化
引用 r1p-&GT; RN 是derefencing一个指向不完全类型
再次(不完全类型是在全球宣布的结构R1
范围内)。

This demonstrates that within the functions, the rn element of struct r2 is a pointer to the incomplete type struct r1 declared at the global scope. Adding a struct r1; as the first line of code inside the function would allow the code to compile, but the initialization referencing r1p->rn is derefencing a pointer to an incomplete type again (the incomplete type is the struct r1 declared at the global scope).

该函数的声明和preceding 结构R1; 线可能
出现在一个标头,如一个不透明的类型。支持功能列表
是不完整的;有好多需要一个方式来获得一个指向
初始化结构R1 来传递到的功能,但是这是一个细节。

The function declarations and the preceding struct r1; line could appear in a header as an opaque type. The list of supporting functions is incomplete; there'd need to be a way to get a pointer to an initialized struct r1 to pass into the functions, but that's a detail.

要在这第二次的恩code工作中,类型结构R1
在全球范围内完整定义的功能面前,
因为递归引用,`结构R21也必须是完整的。

To make the code work in this second TU, the types for struct r1 must be complete in the global scope before the functions are defined, and because of the recursive references, `struct r21 must also be complete.

#include <stdio.h>

/* Logically in a 3-line header file */
struct r1;
extern void z(struct r1 *r1p);
extern void y(struct r1 *r1p);

/* Details private to this TU */
struct r2 { struct r1 *rn; int y; };
struct r1 { struct r2 *rn; int z; };

void y(struct r1 *r1p)
{
    struct r2 p = { r1p,     1 };
    struct r1 q = { r1p->rn, 2 };
    p.rn = &q;
    printf("p.y = %d, q.z = %d\n", p.y, q.z);
}

void z(struct r1 *r1p)
{
    struct r2 p = { r1p,     1 };
    struct r1 q = { r1p->rn, 2 };
    p.rn = &q;
    printf("p.y = %d, q.z = %d\n", p.y, q.z);
}

限定在实现文件而结构的过程
离开类型不完全在公共头文件中可以重复
多个实现文件如果有必要,但如果多个TU
使用完整的结构定义,这将是最好的地方
在私有头文件定义只有文件之间共享该
实施结构。我注意到不要紧是否
专用头precedes或遵循公共头。

This process of defining the structures in the implementation file while leaving the type incomplete in the public header file can be repeated in multiple implementation files if necessary, though if more than one TU uses the complete structure definition, it would be better to place the definitions in a private header file shared only between the files that implement the structures. I note that it does not matter whether the private header precedes or follows the public header.

也许这一切都是有目共睹的你已经。认为它我没有必要
通过这种详细程度之前。

Maybe this was all obvious to you already. I'd not needed to think it through in this level of detail before.

推荐答案

在C 1 ,它们指的是同一类型。 C99第6.2.1节定义存在的范围:

In C1, they refer to the same type. C99 §6.2.1 defines the scopes that exist:

2对于一个标识符指定,每个不同的实体
  标识符是可见的(即,可以使用)只的区域内
  程序文本称为它的范围的。由指定不同的实体
  同一个标识符要么有不同的范围,或者是在不同的名称
  空格。有四种类型的作用域:函数,文件,数据块和
  函数原型。 (A函数原型的声明
  函数声明类型的参数。)

2 For each different entity that an identifier designates, the identifier is visible (i.e., can be used) only within a region of program text called its scope. Different entities designated by the same identifier either have different scopes, or are in different name spaces. There are four kinds of scopes: function, file, block, and function prototype. (A function prototype is a declaration of a function that declares the types of its parameters.)

功能范围仅适用于标签(如明确在同一节稍后说明)。块范围适用于声明的标识符的的 - 块是由复合语句,循环语句和选择语句创建的(而不是由结构声明或复合​​initialisers)。函数原型范围适用于函数原型声明中声明的标识符。

Function scope only applies to labels (as explicitly stated later in the same section). Block scope applies to identifiers declared in blocks - blocks are created by compound-statements, iteration-statements and selection-statements (and not by struct declarations or compound initialisers). Function prototype scope applies to identifiers declared within a function prototype declaration.

这些都不适用于您的例子 - 所有提及结构uperms_entry 在你的例子是在文件范围内。

None of these apply to your example - all of the mentions of struct uperms_entry in your example are at file scope.

C99§6.7.2.3说:

C99 §6.7.2.3 says:

1所有的结构,联合或枚举类型的声明有
  相同的范围,并使用相同的标签声明相同的类型。的类型是不完整的,直到列表的闭括号限定的内容,并完成之后

1 All declarations of structure, union, or enumerated types that have the same scope and use the same tag declare the same type. The type is incomplete until the closing brace of the list defining the content, and complete thereafter.

这是pretty明确的,并适用于你的情况。

This is pretty clear, and applies to your case.

这部分的第8段适用于第一次提到结构uperms_entry

Paragraph 8 of that section applies to the first mention of struct uperms_entry:

8如果窗体的类型说明符的结构-或工会的标识符的发生
  比上述形式之一,因为一部分,并没有其他的申报等
  的标识符当作标签,是可见的,那么它声明一个不完整
  结构或联合类型,并声明标识符的标签
  该类型。

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.

因此​​,在这一点上它的声明在文件范围不完全类型。第6款适用于第二提结构uperms_entry

So at that point it's declared as an incomplete type at file scope. Paragraph 6 applies to the second mention of struct uperms_entry:

6形式的类型说明符的结构-或工会
  标识符<子>选择 {结构声明列表}
枚举
  标识符{枚举列表}
枚举标识符{枚举列表
  ,}
的声明结构,联合或枚举类型。该列表定义
  结构的内容,工会的内容,或枚举的内容。如果
  标识符提供,类型说明符也声明
  标识符是该类型的标签。

6 A type specifier of the form struct-or-union identifieropt { struct-declaration-list } or enum identifier { enumerator-list } or enum identifier { enumerator-list , } declares a structure, union, or enumerated type. The list defines the structure content, union content, or enumeration content. If an identifier is provided, the type specifier also declares the identifier to be the tag of that type.

打完} 在那个typedef声明的最后,这是现在一个完整的类型。

So after the } at the end of that typedef declaration, it's now a complete type.

该附件的问题是没有实际意义。

The adjunct questions are moot.



1。我认为,这是的的C ++中的情况下,然而


1. I believe that this is not the case in C++, however.

这篇关于请问C标准认为有一两个'结构uperms_entry“类型这个头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆