【问题标题】:Someone is using the struct name as a variable name too. What does the code really say?有人也将结构名称用作变量名。代码到底在说什么?
【发布时间】:2010-04-20 17:22:55
【问题描述】:

今天早上我们发现了一段导致库调用崩溃的旧代码。

struct   fred
{
    int     a;
    int     b;
    int     c;
};

fred     fred[MAX_SIZE+1];

memset( fred, 0, sizeof(fred) * MAX_SIZE+1 );

看来 sizeof(fred) 可能是整个数组大小,而不是结构大小,因为它覆盖了大量内存。

它在几个不同的系统上编译时没有警告的事实似乎很奇怪。

对于这种类型和变量名冲突的情况是否有正确的语义? 或者这是某种未定义的行为?还是只是一个缺陷?

【问题讨论】:

  • 代码的真正含义是什么? 它说您组织中的某个人需要严厉的谈话。谁认为这是个好主意?
  • @rlbond - 编码员早已不在,但他的记忆犹存。
  • 我觉得有趣的是,“EvilTeach”会发布这种邪恶的代码...... :)

标签: c++ naming-conventions


【解决方案1】:

第一个是,不要这样做,因为它会令人困惑 - 但你已经发现了这一点。

变量隐藏了结构体的名字,但你仍然可以使用struct fred来引用类型。

例如

fred     fred[MAX_SIZE+1];

memset( fred, 0, sizeof(struct fred) * (MAX_SIZE+1) );

或者,为什么不直接使用完整对象的大小。这样,您的 memset 调用在数组大小或类型发生变化时是稳健的。你可以这样做:

memset( fred, 0, sizeof fred );

必须在使用带有sizeof 的类型ID 时使用括号,但在使用对象时则不需要。

【讨论】:

    【解决方案2】:

    这不应该是 sizeof(fred)*(MAX_SIZE+1) 因为你的数组是 MAX_SIZE+1 长吗?

    【讨论】:

    • 是的。这当然是额外的邪恶。 +1
    【解决方案3】:

    最新的声明优先:

    [C++03: 9.1/2]: 类定义将类名引入到定义它的作用域中,并将该名称的任何类、对象、函数或其他声明隐藏在封闭作用域中(3.3)。 如果在一个范围内声明了一个类名,其中还声明了一个同名的对象、函数或枚举器,那么当两个声明都在范围内时,只能使用 elaborated- 来引用该类类型说明符 (3.4.4)。

    详细类型说明符是当您将structclass 粘贴在类型的前面时;但是,严格来说,这有效地消除了歧义,并且由于上面引用的规则,查找从一开始就从来没有真正模棱两可。

    所以:

    void foo()
    {
       struct bar {};
       bar bar[5];
    
       memset(bar, 0, sizeof(bar));
       //             ^^^^^^^^^^^
       //                  5
    
       memset(bar, 0, sizeof(struct bar));
       //             ^^^^^^^^^^^^^^^^^^
       //                  1
    }
    
    // (NB. Exact sizes may differ; 1 and 5 given as relative examples only)
    

    这一切都是明确定义的,这是您没有收到警告的原因之一。尽管如此,我希望智能编译器会将您的代码发现为可能的程序员错误 - 合理解释为什么某些给定实现在某些非强制情况下会发出或不发出某些给定警告,但是,在很大程度上是愚蠢的。

    【讨论】:

    • 奇怪,为什么没有更多的赞成票?它引用了标准! =)
    【解决方案4】:

    当您定义变量时,它隐藏了类型的名称,所以是的,当您执行sizeof(fred) 时,您得到的是数组的大小,而不是结构的大小。只需打印出sizeof(fred) 即可很容易地验证这一点。

    然而,简短的回答是:“不要那样做。”

    【讨论】:

      【解决方案5】:

      除了运行时大小的情况外,使用memset(以及memcpymalloc等)的典型惯用方式是这样做

      memset(dst_ptr, 0, sizeof *dst_ptr);
      

      或者,等价的,

      memset(&dst_object, 0, sizeof dst_object);
      

      在这种情况下应该如何使用它

      memset(&fred, 0, sizeof fred);
      

      并且不会出现名称冲突的问题。 memset(fred, 0, sizeof fred) 变体也可以使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-13
        • 1970-01-01
        • 2021-01-10
        • 2011-05-19
        • 2023-03-19
        • 2021-04-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多