代码之家  ›  专栏  ›  技术社区  ›  deft_code

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

  •  11
  • deft_code  · 技术社区  · 16 年前

    我最近被一只小虫子咬了。

    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
    

    如果你有上帝般的代码审查能力,你会发现我忘记了 , 之后 "two" .

    在花了相当大的力气找到那个bug之后,我不得不问 为什么会有人想要这种行为?

    我知道这对宏魔法有何帮助,但为什么在像Python这样的现代语言中这是一个“特性”?

    您是否在生产代码中使用过字符串文字连接?

    10 回复  |  直到 16 年前
        1
  •  4
  •   Shafik Yaghmour    11 年前

    我看到几个 C C++ 答案,但没有真正的答案 为什么? 或者说,这个特性的基本原理是什么?在 C++ 这是功能来自 C99 我们可以通过 Rationale for International Standard—Programming Languages—C 部分 6.4.5 字符串常量 上面说的话( 重点矿井 ):

    可以使用反斜杠“换行符”继续将字符串跨多行继续,但这要求字符串的继续从下一行的第一个位置开始。 允许更灵活的布局 为了解决一些预处理问题(见_6.10.3),C89委员会引入了字符串文字连接。一行中的两个字符串文本粘贴在一起,中间没有空字符,以形成一个组合的字符串文本。这是对C语言的补充 允许程序员将字符串文字扩展到物理行末尾之外,而不必使用反斜杠“换行”机制 从而破坏了程序的缩排方案。 未引入显式连接运算符,因为该连接是一个词法构造 而不是运行时操作。

    蟒蛇 这似乎有同样的原因,这减少了对丑陋的需要 \ 继续使用长字符串文本。在第节中介绍 2.4.2 String literal concatenation python语言引用 .

        2
  •  22
  •   Carl Norum    16 年前

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

    char *someGlobalString = "very long "
                             "so broken "
                             "onto multiple "
                             "lines";
    

    不过,最好的原因是使用奇怪的printf格式,比如强制输入:

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

    有很多这样的定义,如果您有类型大小的需求,它们可以派上用场。全部检查一下 at this link . 举几个例子:

    PRIo8 PRIoLEAST16 PRIoFAST32 PRIoMAX PRIoPTR
    
        3
  •  17
  •   R Samuel Klatchko    16 年前

    这是一个很好的特性,允许您将预处理器字符串与字符串组合在一起。

    // 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));
    
        4
  •  5
  •   Charles Duffy    16 年前

    可能有用的情况:

    • 生成包含由预处理器定义的组件的字符串(这可能是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 ".");
    
        5
  •  3
  •   Dan McCormick    16 年前

    从python词汇分析参考,第2.4.2节:

    此功能可用于减少 要拆分的反斜杠数 长的绳子很容易穿过长的 行,甚至添加注释到 部分字符串

    http://docs.python.org/reference/lexical_analysis.html

        6
  •  2
  •   Tomas Petricek    16 年前

    我不确定其他编程语言,但例如C不允许您这样做(我认为这是一件好事)。就我所知,如果您可以使用一些特殊的操作符来进行字符串串接,那么大多数显示C++中有用的例子仍然有效。

    string someGlobalString = "very long " +
                              "so broken " +
                              "onto multiple " +
                              "lines"; 
    

    这可能不太舒服,但肯定更安全。在您的激励示例中,除非您添加 , 分离元素或 + 连接字符串…

        7
  •  1
  •   user12345    16 年前

    以便可以跨行拆分长字符串文本。

    是的,我在生产代码中看到过。

        8
  •  1
  •   Nils von Barth    11 年前

    为了理据,扩展和简化Shafik Yaghmour的答案:字符串文字串接起源于C(因此由C++继承),和这个词一样,有两个原因(引用来自 Rationale for the ANSI C Programming Language ):

    • 格式设置:允许长字符串文字跨越多行,并使用适当的缩进“与行继续相反,这会破坏缩进方案。( 3.1.4 String literals ;及
    • 对于宏magic:允许通过宏(通过字符串化)构造字符串文本( 3.8.3.2 The # operator )

    它包含在现代语言python和d中,因为它们从c中复制了它,尽管在这两种语言中,它都被建议用于贬低,因为它很容易出错(如您所注意的),而且是不必要的(因为可以只使用一个连接操作符和 constant folding 对于编译时评估,您可以在C语言中这样做,因为字符串是指针,所以您可以添加它们。

    删除并不简单,因为这会破坏兼容性,您必须小心优先级(在词法分析期间,在运算符之前会发生隐式连接,但用运算符替换它意味着您需要小心优先级),因此它仍然存在。

    是的,它在用过的生产代码中。 Google Python Style Guide : Line length 指定:

    当一个文本字符串不能放在一行上时,使用括号来进行隐式的行连接。

    x = ('This will build a very long long '
         'long long long long long long string')
    

    参见 String literal concatenation _在维基百科了解更多细节和参考资料。

        9
  •  0
  •   Jerry Coffin    16 年前

    我在C和C++中都有。顺便说一下,我看不出它的实用性和语言的“现代性”有多大关系。

        10
  •  0
  •   Stewart    15 年前

    虽然人们已经从我的嘴里说出了这个功能的实际用途,但迄今为止还没有人试图为语法的选择辩护。

    据我所知,这样可能漏掉的打字错误可能只是被忽视了。毕竟,丹尼斯的头脑中似乎没有对打字错误的稳健性,如下面所示:

    if (a = b);
    {
        printf("%d", a);
    }
    

    此外,还有一种可能的观点认为,不值得使用额外的符号来连接字符串文本——毕竟,对于其中的两个字符,没有其他方法可以完成,而且如果有一个符号,可能会产生尝试将其用于运行时字符串连接的诱惑,这高于C的内置功能级别。

    一些基于C语法的现代高级语言已经放弃了这种表示法,大概是因为它容易出错。但是这些语言有一个字符串连接的操作符,例如 + (JS,C) . (Perl,PHP), ~ (D,尽管这也保持了C的并置语法),但持续折叠(无论如何,在编译语言中)意味着没有运行时性能开销。