我知道使用字符串文字初始化char
数组是完全可能的:
char arr[] = "foo";
C ++ 11 8.5.2 / 1这样说:
char
数组(无论是普通char
,signed char
还是unsigned char
),char16_t
数组,char32_t
数组,还是wchar_t
数组可以通过狭义字符文字char16_t
字符串文字char32_t
字符串初始化 文字或宽字符串文字,或者用括号括起来的适当类型的字符串文字。 字符串文字值的连续字符初始化数组的元素。 ...
但是,您是否可以对条件表达式中的两个字符串文字执行相同的操作?例如:
char arr[] = MY_BOOLEAN_MACRO() ? "foo" : "bar";
(MY_BOOLEAN_MACRO()
扩展为1
或0
)。
C ++ 11 5.16(条件运算符)的相关部分如下:
1 ...第一个表达式在上下文中转换为
bool
(第4条)。 它被评估,如果它是true
,条件表达式的结果是第二个表达式的值, 否则第三个表达。 ...4如果第二个和第三个操作数是相同值类别的glvalues并且具有相同的类型,则结果 属于该类型和值类别,如果第二个或第三个操作数是位字段,则它是位字段,或者如果 两者都是比特字段。
请注意,文字的长度相同,因此它们都是const char[4]
类型的左值。
GCC one ideone接受构造。但是从阅读标准来看,我根本不确定它是否合法。有没有人有更好的见解?
答案 0 :(得分:10)
另一方面,clang
不接受此类代码( see it live ),我相信clang
在这方面是正确的( {{3 }} 的)。
字符串文字由2.14.5
部分中的语法定义:
string-literal:
encoding-prefixopt" s-char-sequenceopt"
encoding-prefixoptR raw-string
并且本节的第一段说明(强调我的):
字符串文字是一系列字符(如2.14.3中所定义) 用双引号包围,可选择以R,u8,u8R,u,uR为前缀, U,UR,L或LR,如“......”,R“(...)”,u8“......”,u8R“(...)”, 你“......”,uR“〜(...)〜”,U“......”,UR“zzz(...)zzz”,L“......”,或LR“(...)”, 分别
并进一步说明了字符串文字的类型是:
“n const char数组”,
以及:
具有静态存储持续时间
但是具有静态存储持续时间的“n const char”,数组不是字符串文字,因为它不符合语法,也不适合段落{{ 1}}。
如果我们使用非常量表达式( MSVC also rejects this code ),我们可以在1
上失败:
gcc
这意味着它可能是一个扩展名,但它不符合要求,因为它不会在see it live中产生警告,即使用bool x = true ;
char arr[] = x ? "foo" : "bar";
。来自-std=c++11 -pedantic
[intro.compliance] 部分:
[...]需要实施来诊断使用此类程序的程序 根据本国际组织的不良扩展 标准。但是,这样做之后,他们就可以编译并执行这样的操作 程序
答案 1 :(得分:3)
这适用于C ++ 11或更新版本的GCC ,因为您提供的文字在编译期间是确定性的(例如,它们是constexpr
)。由于编译器可以确定哪一个是真的,因此可以确定使用哪一个。
要删除constexpr
能力,请尝试以下操作:
#include <iostream>
#include <cstdlib>
int main() {
bool _bool = rand();
char arr[] = (_bool) ? "asdf" : "ffff";
std::cout << arr << std::endl;
}
GCC然后出错:
g++ test.cpp -std=c++11
test.cpp: In function ‘int main()’:
test.cpp:6:34: error: initializer fails to determine size of ‘arr’
char arr[] = (_bool) ? "asdf" : "ffff";
^
test.cpp:6:34: error: array must be initialized with a brace-enclosed initializer
我不太清楚标准的文本定义,知道这个有效的地点或原因,但我感觉 有效。
有关constexpr
及其如何影响可兼容性的进一步阅读,请参阅the answer by @ShafikYaghmour in another question。