请考虑以下代码:
#include <stdio.h>
constexpr int f()
{
return printf("a side effect!\n");
}
int main()
{
char a[f()];
printf("%zd\n", sizeof a);
}
我原本希望编译器在printf
内投诉f
,因为f
应该是constexpr
,但是printf
是不。为什么程序compile and print 15?
答案 0 :(得分:11)
该程序格式错误并且不需要根据C++11 draft standard部分7.1.5
constexpr说明符段 5 <进行诊断/ em>其中说:
对于constexpr函数,如果不存在函数参数值 函数调用替换会产生一个常量 表达式(5.19),程序不正确;无需诊断。
并提供以下示例:
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
和第5.19
段 2 表示:
条件表达式是核心常量表达式,除非它 涉及以下之一作为潜在评估的子表达式 [...]
并包括:
- 调用除constexpr构造函数之外的函数 文字类或constexpr函数[注意:重载分辨率 (13.3)照常使用 - 后注];
在这种情况下我们可能更喜欢诊断,它可能只是一个疏忽,我有一个类似情况的错误报告gcc
不会产生错误但我们可能会喜欢它:{{ 3}}。
更新
使用-fno-builtin
标志会导致gcc
生成以下错误:
error: call to non-constexpr function 'int printf(const char*, ...)'
return printf("a side effect!\n");
^
所以gcc
确实会考虑这个格式错误的,当它使用内置版本的printf
时,它会忽略它。
虽然使用-pedantic
稍微不一致会产生以下警告:
warning: ISO C++ forbids variable length array 'a' [-Wvla]
char a[f()];
^
请注意,使用f()
初始化 constexpr 变量:
constexpr int x = f() ;
会产生错误:
error: 'printf(((const char*)"a side effect!\012"))' is not a constant expression
另请注意,在更一般的情况下,不允许编译器将标准库函数标记为 constexpr Is the compiler allowed leeway in what it considers undefined behavior in a constant expression?。