16

在我的 SAX xml 解析回调(XCode 4,LLVM)中,我对这种类型的代码做了很多调用:

static const char* kFoo = "Bar";

void SaxCallBack(char* sax_string,.....)
{
     if ( strcmp(sax_string, kFoo, strlen(kFoo) ) == 0)
     {

     }


  }

假设编译器优化了 strlen(kFoo) 是否安全?

(Apple 示例代码已经预先计算了 strlen(kFoo),但我认为这对于大量常量字符串很容易出错。)

编辑:优化动机:使用 NSXMLParser 在 iPod touch 2G 上解析我的 SVG 地图需要 5 秒(!)。所以,我想切换到 lib2xml,并优化字符串比较。

4

4 回答 4

12

如果您所说的“LLVM”是指铿锵声,那么是的,您可以指望clang -O优化strlen离开。以下是您的函数的代码:

_SaxCallBack:
Leh_func_begin1:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    leaq    L_.str1(%rip), %rsi
    movl    $3, %edx
    callq   _strncmp
    ...

我把strcmpinto改成了strncmp,但是第三个参数确实已经被 immediate 代替了$3

请注意, gcc 4.2.1 -O3 不会优化此strlen调用,并且您只能期望它在您的问题的精确条件下工作(特别是字符串和调用strlen必须在同一个文件中)。

于 2011-04-24T13:46:55.603 回答
12

不要写这样的东西:

static const char* kFoo = "Bar";

您已经创建了一个名为指向常量数据的变量。kFoo编译器可能能够检测到这个变量没有改变并优化它,但如果没有,你已经膨胀了你的程序的数据段。

也不要写这样的东西:

static const char *const kFoo = "Bar";

现在你的变量kFooconst-qualified 且不可修改的,但如果它用于位置无关的代码(共享库等),内容在运行时仍然会变化,因此它会增加程序的启动和内存成本。相反,使用:

static const char kFoo[] = "Bar";

甚至:

#define kFoo "Bar"
于 2011-04-24T19:47:35.333 回答
2

一般来说,你不能指望它。但是,您可以使用 'sizeof' 并将其应用于字符串文字。当然,这意味着您不能按照最初定义的方式定义“kFoo”。

以下内容应适用于所有编译器和所有优化级别。

#define kFoo "..."

    ... strcmp(... sizeof(kFoo))
于 2011-04-24T16:17:35.620 回答
0

后续问题:

您是否测试过以下内容?

static std::string const kFoo = "BAR";

void SaxCallBack(char* sax_string,.....)
{
  if ( sax_string == kFoo)
  {

  }


}

这是可读性的净胜,但我不知道性能成本。

作为替代方案,如果您必须自己调度,我发现使用类似状态机的方法(带有堆栈)在可读性方面要好得多,并且还可能在性能方面获胜(而不是使用大量标签打开你只有现在可以遇到的标签)。

于 2011-04-26T12:15:53.997 回答