【问题标题】:Why is (void)sizeof(param) not "using" param?为什么 (void)sizeof(param) 不“使用”参数?
【发布时间】:2014-11-14 21:21:02
【问题描述】:

我有一个宏定义如下:

#define UNREF_PARAM_1(a)
    do { \
        (void)sizeof(a); \
    } \
    while (0)

摆脱编译器警告。在我正在进行的一个新项目中,VS2013 突然再次抱怨未引用的形式参数。

奇怪的是,如果我只使用(void)param,它确实有效。 有人知道为什么它在与(void)sizeof(param) 一起使用时不起作用吗?

【问题讨论】:

  • sizeof 在编译时进行评估。
  • 我通常会避免使用此类宏,因为随着时间的推移代码会发生变化,人们会忘记删除它们。我的偏好是在函数头中注释掉参数的名称,这样会抑制警告,并且在不更新代码的情况下无法开始使用参数。
  • 我将这个宏用于调试构建,我希望某些函数什么都不做,并且不会收到有关未引用参数的警告。现在我在 (void)sizeof(a); 之前添加了一个 __pragma(warning(suppress:4100));说明

标签: c++ visual-studio language-lawyer compiler-warnings suppress-warnings


【解决方案1】:

因为在sizeof(param) 中,param 是一个所谓的未求值操作数,因此不是 odr-used - 也就是说,在运行时不需要。

但是,(void)param 确实构成了 odr 使用。

在您的代码中使用该符号的强制转换在内部调用 static_cast。 [expr.static.cast]/6:

任何表达式都可以显式转换为类型cv void,在 在这种情况下,它会变成废弃值表达式(第 5 条)。

[expr]/10:

在某些情况下,表达式仅出于其副作用而出现。这样的表达式称为丢弃值表达式。计算表达式并丢弃其值。 [...] 仅当表达式是 volatile 限定类型的左值时才应用左值到右值转换 (4.1) [...]

[basic.def.odr]/2:

一个表达式可能被计算,除非它是一个未计算的操作数(第 5 条)或其子表达式。名称显示为潜在评估的变量 表达式是odr-used 除非它是一个满足 出现在常量表达式(5.19)中的要求和 立即应用左值到右值转换 (4.1)

此引用的第一部分指定 sizeof(a) 不是 a 的 odr 使用,因为 a 是未计算的操作数1
显然(void)a 可能被评估。而且因为a 肯定既不允许出现在常量表达式中,也不允许声明volatile,所以没有“立即应用”左值到右值的转换,因此a 是odr-used。


1) 以下是表达式列表,其中x 是 C++11 中未计算的操作数:

  • typeid(x),其中x 不是多态类类型的泛左值
  • sizeof(x)(和sizeof x
  • noexcept(x)
  • decltype(x)
  • alignof(x)? alignas(x)?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    相关资源
    最近更新 更多