2014-01-10 69 views
3

我想將不可打印的ASCII字符轉換爲二進制。下面是代碼:將不可打印的ASCII字符轉換爲二進制

int main(int argc, char *argv[]) 
{ 
    char str[32]; 
    sprintf(str,"\x01\x00\x02"); 

    printf("\n[%x][%x][%x]",str[0],str[1],str[2]); 
    return 1; 
} 

我期望輸出應爲[1] [0] [2],但它打印[1] [0] [4]。

我在這裏做錯了什麼?

+1

我認爲它與「\ x00」有關。例如,如果我用\ x01替換上例中的「\ x00」,則輸出爲文件[1] [1] [2] ...仍然混淆 –

+0

注意:要以便攜方式確定是否存在'int '是可打印的字符,使用'#include isprint(x)'。 – chux

回答

5

C字符串以空字節結尾,所以sprintf只能讀取到\x00。相反,你可以使用memcpylike this),或簡單地用

char str[32] = "\x01\x00\x02"; 
+0

它的工作..謝謝 –

6

sprintf操作的字符串字面在\x00一審結束初始化,因爲NUL(U + 0000)終止字符串在C.(當你在字符串文字中寫\x00時,編譯器沒有抱怨,這可以說是語言的一個錯誤特徵。)因此str[2]訪問未初始化的內存,程序有權打印完整的廢話甚至崩潰。

去做你想要做什麼,只是消除sprintf

int main(void) 
{ 
    static const unsigned char str[32] = 
    { 0x01, 0x00, 0x02 }; // will be zero-filled to declared size 

    printf("[%02x][%02x][%02x]\n", str[0], str[1], str[2]); 

    return 0; 
} 

(二進制數據應始終保存在無符號字符,而不是簡單的字符數組;或者uint8_t如果您有它。因爲U + 0000終止字符串,我認爲使用數組文字而不是字符串文字編寫嵌入式二進制數據是更好的方式;但它更多的是鍵入,這是因爲在編譯時數據永遠不會被修改和知道;程序會在沒有它的情況下運行。如果你不打算,請不要聲明argcargv使用它們。返回零,而不是一個,從main來表示成功完成)

(使用sprintf你使用它的方式是其他原因一個壞主意:舉例來說,如果你的二進制塊包含\x25(也稱爲%在ASCII),它會嘗試讀取附加的待格式化參數,並再次打印完整的無意義或崩潰。如果您有充分的理由不使用靜態初始化數據,那麼複製二進制數據塊的正確方法是memcpy。)

+0

你r rite ..我現在明白了.. thks –

+0

+1,因爲這個解決方案很好地處理非ASCII像''\ x80''使用unsigned。然後將其打印爲「[0x80]」而非「[ffffff80]」。 – chux

3

「\ x00」過早終止作爲sprint()的第二個參數的格式字符串。顯然這是無意的,但是sprint()沒有辦法知道第一個NUL不是最後一個NUL。所以它的工作格式字符串實際上比你想要傳遞的更短。

相關問題