【问题标题】:Zero as a function name零作为函数名
【发布时间】:2012-04-30 23:06:33
【问题描述】:

以下示例编译(尽管 VS2010 C++ 编译器发出警告 C4353)并且表达式 (*) 计算结果为 0

#include <iostream>
#include <string>

int main()
{
   0(1, "test"); // (*) - any number and type of arguments allowed       
   int n = 0(1, "test"); // 0
   std::string str(0(1, "test")); // Debug assertion fails - 0 pointer passed
}

是使用 0 作为 C++ 标准允许/规定的函数名称,还是它的解析是特定于编译器的? 我正在查看 N3242 草案,但找不到与此相关的任何内容。 Microsoft 编译器显然将此类构造(或带有__noop 的构造)解析为值为0 的整数。

警告 C4353:

警告 C4353:使用了非标准扩展:常量 0 作为函数 表达。改用 __noop 函数内在函数

【问题讨论】:

  • 我认为这不应该编译,函数名不能以数字开头
  • 这可能是一些愚蠢的 MSVC 东西,具有特定的、模糊的目的。它不能在 GCC 中编译(从警告中可以看出)。
  • 嗯...“使用的非标准扩展”的哪一部分让您相信标准可能允许该构造?
  • @n.m.呃,我忽略了那个明显的暗示。谢谢!
  • @chris : 让我看看... gcc 添加了一个非标准扩展名(例如__attributes__),这是一件好事。 MSVC自己加了,就?断言你一无所知的东西一定是有逻辑吗?

标签: c++ function visual-c++ compiler-construction


【解决方案1】:

函数名是标识符,标识符需要以非数字开头(第 2.11 节):

identifier:
    identifier-nondigit
    identifier identifier-nondigit
    identifier digit

【讨论】:

  • 这解释了一切。谢谢!
  • 函数名肯定是标识符,但函数调用中左括号之前的部分不一定是标识符。例如my_functions[0]() 是一个完全合法的函数调用。 ( ( int(*)() ) 0) () 也是如此。因此,如果存在从 intint(*)() 的隐式转换,0() 也将完全有效(除了它会取消引用空指针并因此调用 UB - 但它会编译是我的观点)。跨度>
  • @sepp2k:是的,允许其他引用函数的方式,但具体问题是:“是否允许使用 0 作为函数名......”,答案显然是“没有”。
  • @JerryCoffin 我不同意“不”,我不同意“因为它不是有效的函数名”。
【解决方案2】:

我不知道答案,但我相信我们可以通过谷歌搜索找到它...

看MSDN,找到两个链接:

第二个链接解释了__noop

__noop 内在函数指定应忽略函数并解析参数列表,但不为参数生成代码。它旨在用于采用可变数量参数的全局调试函数。

这个例子表明__noop对于调试代码来说确实非常有趣:

#if DEBUG
    #define PRINT printf_s
#else
    #define PRINT __noop
#endif

int main() { PRINT("\nhello\n"); }

同一页面上的另一条评论给出了0函数的历史提示:

编译器在编译时将 __noop 内在函数转换为 0。

我猜,曾几何时,这个扩展被称为0,而不是__noop,后来微软创建了__noop关键字,因为它更容易搜索,更易读,不那么“奇怪” " 比这个 0 的东西,并清楚地标记为扩展(因为两个前导下划线,如 MSVC 的 __declspec 或 gcc 的 __attribute__)。

结论:0呢?

  • 这是一个扩展(根据警告消息)
  • 这是一个已弃用的历史扩展
  • 不推荐使用它,取而代之的是__noop
  • 至少在 VC++2003 时(如果不是之前)已弃用它

【讨论】:

  • +1 这个问题的背景实际上是我对禁用/取消定义函数的小研究,灵感来自今天早些时候出现在这里的问题 (stackoverflow.com/questions/10226151/…)。我正在尝试将 #define-ing 函数设置为 0,__noop 并未指定标记(在这种情况下,括号内的参数列表将编译为逗号运算符表达式并将最后一个参数作为表达式值)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
  • 2020-10-20
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 2012-06-01
  • 2012-05-29
相关资源
最近更新 更多