2016-12-31 65 views
-2

由於某些原因,當我打開一個文件並在Python和C中逐字節地讀取它並嘗試打印結果時,我得到隨機字符/數據混合在其中。在C和Python的終端中獲取隨機字符

例如,當我讀了前8個字節的PNG圖像,如下面的例子:

/* Test file reading and see if there's random data */ 

#include <stdio.h> 
#include <stdlib.h> 
#include <malloc.h> 

#define PNG_BYTES_TO_CHECK 8 

int 
main(void) 
{ 
    char fname[] = "../images/2.png"; 

    FILE *fp = fopen(fname, "rb"); 
    if (fp == NULL) abort(); 

    char *buffer = (char *)malloc(PNG_BYTES_TO_CHECK); 

    if (fread(buffer, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) 
     abort(); 

    unsigned i; 
    for (i = 0; i < PNG_BYTES_TO_CHECK; ++i) printf("%x ", buffer[i]); 
    printf("\n"); 

    free(buffer); fclose(fp); 

    return 1; 
} 

我得到這個垃圾到stdout:

ffffff89 50 4e 47 d a 1a a 

但是,當我打開該文件一個十六進制編輯器,字節是完全沒有(這是一個有效的PNG簽名):

enter image description here

任何想法,以什麼可能會導致此?我沒有Python的例子,但是我記得前幾天我在處理字節級別的文件和打印內容時重複使用了mumbo jumbo。

+1

[不要在C中拋出malloc的結果](http://stackoverflow.com/q/605845/995714) –

+1

爲什麼你說這是垃圾? –

+0

@LưuVĩnhPhúc感謝您的鏈接,我以前沒有遇到過。 – bjd2385

回答

0

png spec指出一個PNG文件應該始終以字節137 80 78 71 13 10 26 10開頭。有符號字節的最大值是127,這意味着第一個字節的值溢出並變爲-119(如果這樣會造成混淆,請檢查the way negative numbers are represented)。然後您將其打印爲無符號的十六進制整數。爲此,有符號的字節被提升爲一個整數。同樣,由於表示負數的方式,其值爲-119的4字節整數具有以下二進制表示:11111111111111111111111110001001%x無符號的十六進制值的格式說明符。因爲它認爲你賦予它的值是無符號的,所以它不會將該二進制解釋爲它表示爲負數。如果將11111111111111111111111110001001轉換爲十六進制,則會看到它是ffffff89

tl; dr:文件沒有問題。你只是忘了讓你的字節無符號。

+0

帶符號的整數不能溢出。它調用未定義的算術運算行爲,並且無符號到有符號的轉換是實現定義的,buit不會溢出,也不保證產生特定的結果。並且將錯誤的類型傳遞給'printf'也會調用UB。沒有用於研究爲什麼顯示特定行爲。 – Olaf