为什么允许串联字符串文字?

def*_*ode 11 c c++ python d string-literals

我最近被一个微妙的bug咬了.

char ** int2str = {
   "zero", // 0
   "one",  // 1
   "two"   // 2
   "three",// 3
   nullptr };

assert( int2str[1] == std::string("one") ); // passes
assert( int2str[2] == std::string("two") ); // fails
Run Code Online (Sandbox Code Playgroud)

如果你有神圣的代码审查权力,你会注意到我忘记了,"two".

经过相当大的努力找到这个bug我必须问为什么有人会想要这种行为?

我可以看到这对宏魔术有什么用处,但是为什么这是像python这样的现代语言中的"特征"?

您是否曾在生产代码中使用字符串文字串联?

Car*_*rum 22

当然,这是使代码看起来很好的简单方法:

char *someGlobalString = "very long "
                         "so broken "
                         "onto multiple "
                         "lines";
Run Code Online (Sandbox Code Playgroud)

但最好的原因是对于奇怪的printf格式,如类型强制:

uint64_t num = 5;
printf("Here is a number:  %"PRIX64", what do you think of that?", num);
Run Code Online (Sandbox Code Playgroud)

有很多定义的,如果你有类型大小要求它们可以派上用场.通过此链接查看所有内容.几个例子:

PRIo8 PRIoLEAST16 PRIoFAST32 PRIoMAX PRIoPTR
Run Code Online (Sandbox Code Playgroud)


R S*_*hko 17

这是一个很棒的功能,允许您将预处理器字符串与字符串组合在一起.

// Here we define the correct printf modifier for time_t
#ifdef TIME_T_LONG
    #define TIME_T_MOD "l"
#elif defined(TIME_T_LONG_LONG)
    #define TIME_T_MOD "ll"
#else
    #define TIME_T_MOD ""
#endif

// And he we merge the modifier into the rest of our format string
printf("time is %" TIME_T_MOD "u\n", time(0));
Run Code Online (Sandbox Code Playgroud)

  • @STingRaySC - 虽然我同意在C++中有更好的方法可以做到这一点,但他的问题也被标记为C(这是非常有用的). (2认同)
  • 将`printf`(和朋友')格式字符串作为编译时常量有一个非常好的理由 - 编译器可以告诉您参数类型是否与格式字符串不匹配. (2认同)
  • @STingRaySC - printf 可以优化为一系列特定于该字符串中包含的格式的调用,而不是作为单个库调用实现 - 这就是为什么它的第一个参数只需要一个常量字符串!如果您正在为一个小型嵌入式平台进行编译,那么不需要使用包含大量您永远不会使用的代码的全能打印功能,将是一个巨大的胜利(并且请记住,嵌入式空间是一个的市场 C 仍然占主导地位,所以有很多人这很重要)。 (2认同)

Cha*_*ffy 5

这可能有用的案例:

  • 生成字符串,包括由预处理器定义的组件(这可能是C中最大的用例,也是我非常非常频繁地看到的用例).
  • 在多行上拆分字符串常量

为前者提供更具体的例子:

// in version.h
#define MYPROG_NAME "FOO"
#define MYPROG_VERSION "0.1.2"

// in main.c
puts("Welcome to " MYPROG_NAME " version " MYPROG_VERSION ".");
Run Code Online (Sandbox Code Playgroud)


Sha*_*our 5

我看到了几个CC++答案,但没有一个真正回答为什么或这个功能的基本原理是什么?在C++中,此功能来自C99,我们可以通过转到国际标准\xe2\x80\x94Programming Languages\xe2\x80\x94C部分6.4.5 字符串文字的基本原理来找到此功能的基本原理,其中显示(重点是我的):

\n\n
\n

可以使用反斜杠\xe2\x80\x93newline 行延续来跨多行延续字符串,但这要求字符串的延续从下一行的第一个位置开始。为了允许更灵活的布局,并解决一些预处理问题(请参阅\xc2\xa76.10.3),C89 委员会引入了字符串文字连接。将一行中的两个字符串文字粘贴在一起,中间不包含空字符,以形成一个组合字符串文字。C 语言的这一新增功能允许程序员将字符串文字扩展到物理行末尾之外,而无需使用反斜杠\xe2\x80\x93newline 机制,从而破坏程序的缩进方案。未引入显式串联运算符,因为串联是词法构造而不是运行时操作。

\n
\n\n

Python\\这似乎也有同样的原因,这减少了丑陋的继续长字符串文字的需要。\n The Python Language Reference的2.4.2 字符串文字连接部分对此进行了介绍。

\n