【问题标题】:initialize a C string with multiple quoted strings用多个带引号的字符串初始化 C 字符串
【发布时间】:2009-12-01 01:22:36
【问题描述】:

我认为一个 C 字符串可以用一个且只有一个带引号的字符串来初始化。我只是想知道这是怎么回事?

char const help_message [] =   
   "Usage: %s [options] files ...\n"   
   "\n"   
   "Options include:\n"   
   " --verbose -v    Be verbose\n"   
   " --help -h       Print this help message\n"   
   " --output -o     Specify output file\n"     
   "\n" ;   

 printf (help_message, argv [0]) ;

【问题讨论】:

  • 我猜你想错了:-)

标签: c string


【解决方案1】:

compiler 会自动连接相邻的字符串。

这对于提高可读性非常有用,如您的示例或一些预处理器函数:

#define LOG(x) printf("%s", "Logging: " x)

LOG("HeyHey");

相当人为的例子,但明白了重点。

【讨论】:

  • 如果字符串可能包含% 字符,则不会。不过puts("Logging: " x) 是有可能的。
  • @Johannes:就像 caf 所说的那样,printf 的第一个参数是要格式化的字符串,我打算避免这种情况(另外,这是防止缓冲区攻击的自然反应)。实际上,这个函数实际上可能会受益于将x"Logging: " 一起放入,以便进行格式化。
  • printf("Logging: %s", x) 更有意义,并且不需要 x 是字符串文字。不要忘记 puts 添加了一个示例中没有的换行符(fputs 没有)。
  • @caf:在这种情况下,包含% 字符的字符串会有什么问题???
  • AndreyT: printf("something with %s")(注意没有更多参数)是一个错误。这将导致编译时问题(GCC 的 -Wformat)或未定义的行为。
【解决方案2】:

相邻的字符串文字被连接起来,这在两种方法中很有用:组合字符串和可视化多行字符串文字,例如上面的。比较该代码的其他外观:

char const help_message[] = "Usage: %s [options] files ...\n\nOptions include:\n --verbose -v    Be verbose\n --help -h       Print this help message\n --output -o     Specify output file\n\n";

想象一下尝试保持这种状态。此外,如果您使用多行字符串文字,则必须转义换行符或处理源代码使用的任何内容,可能不是'\n',并且您必须仔细观察缩进。所有这些都使您的示例中的代码更好。

这是一个宏案例的例子:

#define STRINGIZE_(v) #v
#define STRINGIZE(v) STRINGIZE_(v)

#define LOCATION __FILE__ ":" STRINGIZE(__LINE__)

#define MY_ASSERT(expr) do { \
   if (!(expr)) \
     some_function(LOCATION ": assertion failed in " \
                   __PRETTY_FUNCTION__ ": " #expr); \
} while (0)

(还有其他替代方法,例如传递单独的参数,并使用 GCC 特定的 __PRETTY_FUNCTION__ 就像 deprecated 一样,但其余的都很方便,这是一个不错的“真实”示例,恕我直言。 )

该代码中提出的其他需要注意的问题:

  • 单个# 是预处理器字符串化操作符(## 是另一个特殊的预处理器操作符,用于标记粘贴)
  • 没有第二个字符串化宏,你会得到"filename.c:__LINE__"
  • 使用 do-while 不会破坏 if-else,并且需要将宏用作语句而不是表达式
    • 防止将其用作表达式并不总是有帮助,但对于类似断言的宏来说,这是您想要的

中断 if-else 示例:

if (cond) MY_ASSERT(blah);
else other();

扩展到:

if (cond) do { ... } while(0);
else other();

代替:

if (cond) if (...) ...;
else other();

这是不正确且令人惊讶的:

if (cond) {
  if (...) {
    ...;
  }
  else {
    other();
  }
}

【讨论】:

    【解决方案3】:

    因为相邻的带引号的字符串被编译器认为是同一字符串的一部分。 C 的语法特别允许这样做。

    【讨论】:

      【解决方案4】:

      不要与字符串数组混淆:

      {"xxx" ,
      "yyyy",
      "3534"}
      

      你发布的是一个字符串。

      【讨论】:

        【解决方案5】:

        您的初始化程序仅包含一个字符串文字。在翻译的第 6 阶段(预处理之后),看起来像多个 "" 封闭的字符串文字实际上将合并为单个字符串文字。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-08
          • 1970-01-01
          • 1970-01-01
          • 2016-07-27
          • 2019-06-17
          相关资源
          最近更新 更多