2011-04-24 60 views
11

在我的SAX解析XML的回調(的XCode 4,LLVM),我做了很多電話來 這種類型的代碼:我可以指望我的編譯器優化const char *上的strlen嗎?

static const char* kFoo = "Bar"; 

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

    } 


    } 

它是安全的假設的strlen(kFoo)由優化編譯器?

(蘋果的示例代碼 已預先計算的strlen(kFoo),但我認爲這是很容易出錯的大量常量字符串的。)

編輯:動機優化:分析我的SVG地圖上的iPod觸摸2G需要5秒(!)使用NSXMLParser。所以,我想切換到lib2xml,並優化字符串比較。

+0

初學者優化建議:不要。對專家的優化建議:尚未。除非分析表明這是你的程序中的瓶頸,否則我認爲你不應該擔心它。 – freespace 2011-04-24 13:24:05

+2

你的意思是'strncmp',對吧?因爲你可以使用'strcmp'(帶有兩個參數),它就等同於當前寫入的條件。 – 2011-04-24 13:28:12

+4

@freespace問題是「我可以指望我的編譯器優化...?」。除非你認爲這個建議適用於編譯器,否則我不認爲它與這個問題有什麼關係。 – 2011-04-24 13:32:30

回答

6

如果用「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 
    ... 

我改變了strcmpstrncmp,但第三個參數確實已經被眼前的$3取代。

注意,GCC 4.2.1 -O3不優化此strlen調用,你只能期望它在你的問題(的確切條件下工作尤其是,字符串和調用strlen必須在同一文件)。

+1

我檢查了微軟的編譯器。它還優化了使用'/ O2'優化的呼叫。 – 2011-04-24 13:56:24

+2

如果'kFoo'本身被設置爲'const'(例如'static const char * const kFoo =「Bar」;'),gcc會優化'strlen()'的調用。 – caf 2011-04-24 14:21:05

+0

'clang version 2.8'不會在我的機器上沒有第二個'const'的情況下優化'strlen()'。 – jfs 2011-04-24 16:42:35

1

一般來說,你不能指望它。但是,您可以使用'sizeof'並將其應用於字符串文字。當然,這意味着你不能像最初定義的那樣定義'kFoo'。

以下內容適用於所有編譯器和所有優化級別。

#define kFoo "..." 

    ... strcmp(... sizeof(kFoo)) 
+4

請注意,在這種情況下,sizeof(kFoo)== strlen(kFoo)+ 1( 'sizeof'包含終止'NUL') – vladr 2012-04-06 15:51:47

9

不要寫的東西,如:

static const char* kFoo = "Bar"; 

你已經創建了一個變量命名kFoo指向常量數據。編譯器可能能夠檢測到這個變量不會改變並優化它,但是如果沒有,你會膨脹你的程序的數據段。

也不要寫的東西,如:

static const char *const kFoo = "Bar"; 

現在你的變量kFooconst -qualified和不可修改的,但如果它在位置無關的代碼中使用(共享庫等),內容將在運行時仍然會有所不同,因此它會將啓動和內存成本添加到您的程序中。相反,使用:

static const char kFoo[] = "Bar"; 

甚至:

#define kFoo "Bar" 
+0

Cool Thanks R. !! – Jacko 2011-04-25 00:54:03

+7

我不會推薦C++中的'#define'選項,絕對不會!感謝指針問題上的負責人。 – 2011-04-26 12:01:54

+1

問題標記爲C,而不是C++。但是,無論如何,我寧願使用'static const char []'形式。 – 2011-04-26 12:15:19

0

後續問題:

你測試了以下?

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

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

    } 


} 

這是一個可讀性的淨贏,但我不知道性能成本。作爲一種替代方案,如果你必須自己派遣,我發現使用類似狀態機的方法(使用堆棧)具有更好的可讀性,並且也可能贏得性能(而不是大要打開的標籤數量只有現在可以滿足的標籤)。

+0

謝謝,Matthieu。我正在研究一個稱爲Ragel的狀態機生成器,它可以用多種語言生成解析器。 – Jacko 2011-04-28 13:44:58

相關問題