理解令人困惑的 typedef 语法

发布于 2024-12-21 02:38:41 字数 347 浏览 1 评论 0原文

考虑以下代码片段,

typedef int type;
int main()
{
   type *type; // why is it allowed?
   type *k ;// which type?
}

我收到错误'k' is not statements in thisscope。编译器将 type *k 解析为 type*k 之间的乘法。这样的语法是不是很混乱呢?

为什么 C++ 标准允许 type *type ?因为语法是这么说的?为什么?

Consider the following code-snippet

typedef int type;
int main()
{
   type *type; // why is it allowed?
   type *k ;// which type?
}

I get an error 'k' is not declared in this scope. The compiler parses type *k as multiplication between type* and k. Isn't this grammar very confusing?

Why is type *type allowed by the C++ Standard? Because the grammar says so? Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

始于初秋 2024-12-28 02:38:41
type *type; // why is it allowed?

C++11 3.3.2/1 说:

名称的声明点紧接在其完整声明符(第 8 条)之后和其初始值设定项(如果有)之前

因此变量名称 type 直到使用类型名称 之后才会引入>类型;类型名称是声明符中 type 的唯一可用含义。

type *k ;// which type?

局部变量名称隐藏了全局类型名称,因此在此选择。 C++11 3.3.10/1 中对此进行了描述:

可以通过在嵌套声明区域或派生类中显式声明同名来隐藏名称。

当然,完全限定的类型名称 ::type 仍然可用。

type *type; // why is it allowed?

C++11 3.3.2/1 says:

The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any)

So the variable name type is not introduced until after the use of the type name type; the type name is the only available meaning of type during the declarator.

type *k ;// which type?

The local variable name hides the global type name, so that is chosen here. This is described in C++11 3.3.10/1:

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class.

The fully qualified type name, ::type, is of course still available.

娜些时光,永不杰束 2024-12-28 02:38:41

问题实际上是关于变量名何时被定义为标识符,并且语言确定它就在代码中声明变量的点之后:

typedef int type;
int main() {
   type t;   // type refers to ::type
   int       // type still refers to ::type
   type;     // variable declared, this shadows ::type
   type + 1; // type is a variable of type int.
}

在其他上下文中也有类似的规则,这只是一个问题决定何时声明标识符。还有其他类似的情况,例如在类的初始化列表中:

struct test {
   int x;          // declare member
   test( int x )   // declare parameter (shadows member)
   : x(            // refers to member (parameter is not legal here)
        x )        // refers to parameter
   {};
};

或者在成员函数定义中的标识符范围中:

struct test {
   typedef int type;
   type f( type );
};
test::type         // qualification required, the scope of the return type is
                   // at namespace level
test::f(
         type t )  // but the scope of arguments is the class, no qualification
                   // required.
{}

至于决定的理由,我不能告诉你,但它是一致且简单的。

The question is actually about when exactly a variable name is defined as an identifier, and the language determines that it is right after the point in code where the variable is declared:

typedef int type;
int main() {
   type t;   // type refers to ::type
   int       // type still refers to ::type
   type;     // variable declared, this shadows ::type
   type + 1; // type is a variable of type int.
}

There are similar rules in other contexts, and it is just a matter of deciding when identifiers are declared. There are other similar situations, for example in the initialization list of a class:

struct test {
   int x;          // declare member
   test( int x )   // declare parameter (shadows member)
   : x(            // refers to member (parameter is not legal here)
        x )        // refers to parameter
   {};
};

Or in the scope of the identifiers in the definition of member functions:

struct test {
   typedef int type;
   type f( type );
};
test::type         // qualification required, the scope of the return type is
                   // at namespace level
test::f(
         type t )  // but the scope of arguments is the class, no qualification
                   // required.
{}

As of the rationale for the decision, I cannot tell you but it is consistent and simple.

澜川若宁 2024-12-28 02:38:41

这很令人困惑,但这是访问 type 变量的唯一方法。
如果你想使用 type 类型,你可以这样做:

typedef int type;
int main() {
    type *type;
    ::type *k ;
    return 0;
} 

大多数语法怪物都来自于与 C 的向后兼容性。

It is confusing, but this is the only way to get access to type variable.
If you want to use type type you can do:

typedef int type;
int main() {
    type *type;
    ::type *k ;
    return 0;
} 

Most of those grammar monstrosities come from backward compatibility with C.

南风起 2024-12-28 02:38:41

保持命名空间(不是 C++ 意义上的,而是变量/类型命名空间)分离的基本原理是相当明显的:当您不使用类型名称污染变量命名空间时,typedef 上的代码中断就会减少。

假设预先存在的代码带有名为“employee”的变量。如果变量和 typedef 位于同一命名空间中,则为“typedef struct {}雇员;”会破坏现有代码,需要更改变量名称(这在 IDE 出现之前是一个问题)。但是,如果它们共享命名空间,则没有问题,并且人们在大型代码库中选择类型名称时可以少担心一个问题。

The rationale of keeping namespaces (not in the C++ sense, but in variable/type namespace) separate is fairly obvious: When you don't pollute the variable namespace with type names, less code breaks on typedef.

Suppose there was pre-existing code with a variable named "employee". If variables and typedefs lived in the same namespace, a "typedef struct {} employee;" would break the existing code, requiring a change of the variable name (which was more of an issue in pre-IDE days). However, if they do not share a namespace, there is no problem and people have one less issue to worry about when choosing type names in large code bases.

蓦然回首 2024-12-28 02:38:41

我认为这是允许的,可能是因为它为程序员在为其声明的变量选择名称时提供了灵活性。在 C# 中,您可以声明与类型同名的属性:

//C# code
class Manager
{
   public Name Name {get;set;}
};

当我用 C# 编写代码时,我发现此功能非常有用。因为我有更多的名字可供选择。否则,如果我有一个名为 Name 的类型,那么我将无法创建同名的属性,我将被迫选择不同的名称,比如 Name__NamenameNAME 等 - 所有这些都不吸引我。


至于您的代码,由于在范围内(在声明 object type 之后),type 已经是一个变量,因此 type< /em> `类型不能直接引用。但我认为这应该可以很好地编译并根据标准:

typedef int type;
int main()
{
   type *type; // why is it allowed?
   ::type *k ;// which type?
}

演示: http://ideone.com/chOov

I think it is allowed probably because it provides flexibility for programmers when choosing name for the variables they declare. In C#, you could declare property of same name as the type:

//C# code
class Manager
{
   public Name Name {get;set;}
};

When I code in C#, I find this feature very useful. Because I've more options for names to choose from. Otherwise, if I've a type called Name, then I wouldn't be able to create a property of the same name, I would be forced to choose a different name, say Name_, _Name, name, NAME etc - all of which don't appeal to me.


As for your code, since in the scope (after declaration of object type), type is already a variable, the type `type cannot be referred to directly. But I think this should compile fine and according to the Standard:

typedef int type;
int main()
{
   type *type; // why is it allowed?
   ::type *k ;// which type?
}

Demo : http://ideone.com/chOov

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文