是否可以使用有条件选择的字符串文字初始化字符数组?

时间:2015-01-23 16:26:26

标签: c++ language-lawyer string-literals

我知道使用字符串文字初始化char数组是完全可能的:

char arr[] = "foo";

C ++ 11 8.5.2 / 1这样说:

  

char数组(无论是普通charsigned char还是unsigned char),char16_t数组,char32_t数组,还是   wchar_t数组可以通过狭义字符文字char16_t字符串文字char32_t字符串初始化   文字或宽字符串文字,或者用括号括起来的适当类型的字符串文字。   字符串文字值的连续字符初始化数组的元素。 ...

但是,您是否可以对条件表达式中的两个字符串文字执行相同的操作?例如:

char arr[] = MY_BOOLEAN_MACRO() ? "foo" : "bar";

MY_BOOLEAN_MACRO()扩展为10)。

C ++ 11 5.16(条件运算符)的相关部分如下:

  

1 ...第一个表达式在上下文中转换为bool(第4条)。   它被评估,如果它是true,条件表达式的结果是第二个表达式的值,   否则第三个表达。 ...

     

4如果第二个和第三个操作数是相同值类别的glvalues并且具有相同的类型,则结果   属于该类型和值类别,如果第二个或第三个操作数是位字段,则它是位字段,或者如果   两者都是比特字段。

请注意,文字的长度相同,因此它们都是const char[4]类型的左值。

GCC one ideone接受构造。但是从阅读标准来看,我根本不确定它是否合法。有没有人有更好的见解?

2 个答案:

答案 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