我可以依靠我的编译器来优化const char *上的strlen吗?

时间:2011-04-24 13:19:43

标签: c optimization compiler-construction llvm strlen

在我的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 个答案:

答案 0 :(得分:10)

如果“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
    ...

我将strcmp更改为strncmp,但第三个参数确实已被替换为$3

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

答案 1 :(得分:10)

不要写像:

static const char* kFoo = "Bar";

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

也不要写像:

static const char *const kFoo = "Bar";

现在你的变量kFooconst - 合格且不可修改,但如果它用于位置无关代码(共享库等),则内容在运行时仍会有所不同,因此它将会为您的程序添加启动和内存成本。相反,使用:

static const char kFoo[] = "Bar";

甚至:

#define kFoo "Bar"

答案 2 :(得分:2)

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

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

#define kFoo "..."

    ... strcmp(... sizeof(kFoo))

答案 3 :(得分:0)

后续问题:

您是否测试过以下内容?

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

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

  }


}

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

作为替代方案,如果你必须自己发送,我发现使用类似状态机的方法(使用堆栈)更好的可读性,并且也可能在性能方面取得胜利(而不是拥有大量数据)打开的标签只有你现在可以使用的标签。