2011-05-04 50 views
1

我寫了一個小程序,它反轉一個字符串,並將其打印到屏幕:這個程序是兼容的大和小endian系統?

void ReverseString(char *String) 
{ 
    char *Begin = String; 
    char *End = String + strlen(String) - 1; 
    char TempChar = '\0'; 

    while (Begin < End) 
    { 
     TempChar = *Begin; 
     *Begin = *End; 
     *End = TempChar; 
     Begin++; 
     End--; 
    } 
    printf("%s",String); 
} 

它完美地在開發的C++在Windows(小端)。 但我突然懷疑它的效率。如果你看這條線:

while (Begin < End) 

我比較開始和結束的地址。這是正確的方法嗎? 此代碼是否適用於像Mac OS X這樣的大端操作系統? 或者我在想錯誤的方式?

我有上面提到的幾個疑問。 任何人都可以請澄清?

+0

作爲一個次要的挑剔,TempChar在循環之外是毫無意義的,也沒有必要對它進行初始化。在循環內移動它,並使其爲const:const TempChar = * Begin ;. – unwind 2011-05-04 07:10:56

+0

另一個小小的挑剔 - Mac OS X不是大端,它可以是大或小端,因爲它運行在x86(小端),PowerPC(大端)和其他體系結構上。 – 2011-05-04 07:16:29

+1

如果您正在查找問題,則在傳遞位於數組開頭的空字符串時,此代碼具有未定義的行爲 - 無法在「開始之前」指針指向一個空字符串。在實踐中,它可以在平坦記憶模型的任何地方工作,也可能在大多數地方沒有。 – 2011-05-04 08:31:05

回答

6

您的代碼沒有排序相關的問題。你比較兩個指針的方式也沒有問題。總之,你的代碼很好。

+0

你能否詳細解釋一下爲什麼你認爲它是正確的? – Vijay 2011-05-04 06:47:24

+3

@殭屍:你的代碼中只有指針和字符(字節)。這些字節按照定義爲endian-neutral。而你所做的所有指針都是讀,分配,遞增和遞減,所有這些都是端到中立的操作。你解引用字節也是endian中立的。所以一切都很好。 – DarkDust 2011-05-04 07:06:33

1

只要你操縱整個type T對象(這就是你所做的type Tchar)你只是不能遇到字節順序問題。

例如,如果您嘗試在較大的類型中操作單獨的字節(例如int),但您沒有這樣做,您可以運行它們。這就是爲什麼在你的代碼期間不可能存在字節碼問題。

3

Endianness定義爲多字節基元類型中字節的顯着性順序。所以如果你的int是big-endian,這意味着在內存中的int的第一個字節(即具有最低地址的那個)包含int的最高有效位,依此類推到最後/最不重要。那是全部它的意思。當我們說一個系統是big-endian時,這通常意味着它的所有指針和算術類型都是big-endian,儘管這裏有一些奇怪的特殊情況。 Endian-ness不會影響指針算術或比較,也不會影響字符串存儲在內存中的順序。

您的代碼不使用任何多字節基元類型[*],所以endian-ness無關緊要。一般來說,如果您以某種方式訪問​​此類對象的各個字節(例如,通過投射指向unsigned char*的指針,將內存寫入文件或通過網絡等),則字節序只會變得相關。

假設主叫做這樣的事情:

int x = 0x00010203; // assuming sizeof(int) == 4 and CHAR_BIT == 8 
ReverseString((char *)&x); 

然後他們代碼將尾數依賴。在一個big-endian系統中,他們會傳遞給你一個空字符串,因爲第一個字節是0,所以你的代碼將不會改變x。在一個小端系統,他們會通過你三字節的字符串,因爲前三個字節是0x030x020x01,第四個字節爲0,所以你的代碼會改變x0x00030201

[*]以及,指針是多字節的,在OSX和幾乎每個C實現上都是如此。但是你不檢查他們的存儲表示,你只是用它們作爲值,所以沒有機會根據字節順序來區分行爲。