问题 当存在修饰符(L,u8等)时,相邻字符串文字串联会发生什么


它在C和C ++中是有效的,因为预处理器或编译器会破坏字符串文字 连接相邻的字符串文字。

const char *zStr = "a" "b"; // valid

当字符串文字带有前缀时会发生什么 L (宽字符), u (UTF-16), U (UTF-32), u8 (UTF-8)和原始字符串文字(R"foo(this is a "raw string literal" with double quotes)foo")?

例如,允许以下内容:

const wchar_t *zStr = L"a" "b"; // valid?

7189
2018-03-03 10:20


起源



答案:


在C ++ 0x中,根据[lex.string] / p13,您的示例有效:

...如果一个字符串文字没有   encoding-prefix,它被视为一个   字符串文字相同   encoding-prefix作为另一个操作数。   ...

在C ++ 03中,同一部分表示此代码具有未定义的行为:

...如果是一个窄字符串文字标记   与宽字符串文字相邻   令牌,行为未定义。 ...


12
2018-03-03 15:41



谢谢,这似乎是我想知道的! - Benoit
出于好奇,这种特定的未定义行为是否需要编译器在其选择生成发射核导弹的生成代码的情况下发出任何类型的诊断?我可以理解一个标准,允许编译器选择将窄字符串扩展为宽而不进行诊断,或者将这种连接扩展为格式错误,但允许无诊断的未定义行为似乎是所有可能世界中最糟糕的。 - supercat
@supercat:未定义的行为通常意味着任何事情都可能发生。代码可以完全按照您的意图执行。它可以编译,也可能不编译。它可以使计算机悬停在最近的单个栏上。 - Howard Hinnant
@HowardHinnant:为什么标准人员允许在这样的情况下完全未定义的行为,编译器应该清楚 知道 它是否会生成有效的字符串文字?我知道保证悬挂指针访问不会导致鼻子恶魔会是不可接受的昂贵,但是有什么可能的好处是允许不受限制的UB用于格式错误的连接字符串? - supercat
@supercat:我没有给你一个好的答案。我也认为未定义的行为在标准中被过度使用。 C ++委员会有一个研究小组来解决这个问题。我真诚地希望他们积极地这样做。特别是gcc在检测到未定义的行为时进行危险的优化是众所周知的。例如,编译器可以优化在检查溢出时意外创建UB的代码,以便消除溢出检查。这是一个非常糟糕的情况,你不想坐在安全关键环境中运行此类代码的汽车中。 - Howard Hinnant


答案:


在C ++ 0x中,根据[lex.string] / p13,您的示例有效:

...如果一个字符串文字没有   encoding-prefix,它被视为一个   字符串文字相同   encoding-prefix作为另一个操作数。   ...

在C ++ 03中,同一部分表示此代码具有未定义的行为:

...如果是一个窄字符串文字标记   与宽字符串文字相邻   令牌,行为未定义。 ...


12
2018-03-03 15:41



谢谢,这似乎是我想知道的! - Benoit
出于好奇,这种特定的未定义行为是否需要编译器在其选择生成发射核导弹的生成代码的情况下发出任何类型的诊断?我可以理解一个标准,允许编译器选择将窄字符串扩展为宽而不进行诊断,或者将这种连接扩展为格式错误,但允许无诊断的未定义行为似乎是所有可能世界中最糟糕的。 - supercat
@supercat:未定义的行为通常意味着任何事情都可能发生。代码可以完全按照您的意图执行。它可以编译,也可能不编译。它可以使计算机悬停在最近的单个栏上。 - Howard Hinnant
@HowardHinnant:为什么标准人员允许在这样的情况下完全未定义的行为,编译器应该清楚 知道 它是否会生成有效的字符串文字?我知道保证悬挂指针访问不会导致鼻子恶魔会是不可接受的昂贵,但是有什么可能的好处是允许不受限制的UB用于格式错误的连接字符串? - supercat
@supercat:我没有给你一个好的答案。我也认为未定义的行为在标准中被过度使用。 C ++委员会有一个研究小组来解决这个问题。我真诚地希望他们积极地这样做。特别是gcc在检测到未定义的行为时进行危险的优化是众所周知的。例如,编译器可以优化在检查溢出时意外创建UB的代码,以便消除溢出检查。这是一个非常糟糕的情况,你不想坐在安全关键环境中运行此类代码的汽车中。 - Howard Hinnant


是的,C ++ 0x允许该特定示例。前缀和L前缀文字的任何组合都将被视为所有都是L前缀的。

编辑:引文 - N3242(当前C ++ 0x工作草案)§2.14.5/ 13:

在翻译阶段6(2.2)中,连接相邻的字符串文字。如果两个字符串文字具有相同的encoding-prefix,则生成的连接字符串文字具有该encoding-prefix。如果一个字符串文字没有编码前缀,则将其视为与另一个操作数相同的编码前缀的字符串文字。


4
2018-03-03 10:25



谢谢您的回答。你有任何参考支持吗?那么其他前缀怎么样? - Benoit
这是不正确的。 ISO 14882:2003 C ++标准2.13.4 / 3说:在翻译阶段,相邻的窄字符串文字被连接起来,相邻的宽字符串文字被连接起来。 如果窄字符串文字标记与宽字符串文字标记相邻,则行为未定义。 我有Visual C ++编译器 针对不匹配的字符串发出诊断(C2308)。 - In silico
@In silico:如果你想让它被接受,你能不能回答一下?你知道其他前缀吗? - Benoit
有多种标准可供选择,这由c ++ 0x涵盖。 - Hans Passant
@Hans Passant:是的,但也许这些标准在这个主题上达成一致意见? - Benoit