2016-02-26 74 views
3

有人可以爲我解釋一下代碼嗎?這段代碼是怎麼回事?

爲什麼32位UINT

爲什麼0xff

在這裏做什麼4右移?

int writeUINT32little(FILE *f, UINT32 i) 
{  
    int rc;  
    rc = fputc((i & 0xff), f);  
    if (rc == EOF)  return rc;  
    rc = fputc(((i >> 8) & 0xff), f);  
    if (rc == EOF)  return rc;  
    rc = fputc(((i >> 16) & 0xff), f);  
    if (rc == EOF)  return rc;  
    return fputc(((i >> 24) & 0xff), f); 
} 
+8

這在小尾數格式寫入文件的32位無符號整數。 –

+0

檢查寫入文件的函數時出錯。在甚至有用的錯誤檢查很少見的世界中罕見的發現。 – user3386109

+0

後續問題(適用於所有人):你可以在不使用評論的情況下編寫可讀的*嗎? – TobiMcNamobi

回答

8

這需要一個32位無符號整數,並將其輸出到一個文件中,逐字節地將最低有效字節先輸出(即小端)。

0xff是用十進制表示255的十六進制方式,或者用二進制表示11111111。而&是按位and函數。放在一起,(i & 0xff)屏蔽了整數的最低有效字節。

然後,這些移位將整個事物轉移到8位​​,並且該過程重複打印下一個字節。

1

這個函數據說做的是寫一個32位無符號整數到小尾數的文件流中。

它的確在做什麼,而不是做一件簡單的小任務,並且做得對,它會一起做兩件事,並且弄錯了。

我去到爲什麼這是錯之前,我會很快回答這個問題本身:

  • 爲什麼UINT32?不知道。這是非標準的,最好用uint32_t代替。
  • 爲什麼0xff?用作掩碼,將較低的8位保存在較大的變量(32位)中
  • 什麼是4個右移位在這裏?這些移位用於將原始UINT中的每個字節以正確的「小端」順序帶到最右邊的位。


現在,有了這樣的方式......

爲什麼這是錯的?
A char保證是at least 8 bits wide,但它可能要大一些。這意味着fputc可能會爲每次調用寫入8位,但可能會寫入更多。這意味着在一個char(例如)16位的特定體系結構中,該函數將爲每個調用寫入64位,並且它根本不會是小端。此外,該函數非常小心地檢查錯誤,但不會向調用方公開相關的失敗信息(寫入了多少字節?)。

什麼是更好的設計?
首先,一如既往,做一個小的事情,做正確的事:

uint32_t toLittleEndian(uint32_t v) 
{ 
    uint32_t result = v >> 24; 
    result |= v << 24; 
    result |= (v >> 8) & 0xf0; 
    result |= (v << 8) & 0xf00; 
    return result; 
} 

注:此實現是故意冗長。這裏有一個優化的機會,使用鑽頭旋轉的操作,但C沒有原生支持這一點,需要組裝代碼

此功能轉換大端32位值,其等效小端表示(實際上它之間交替這兩個可以被命名爲switchEndian)。

接下來,我們需要將值寫入文件:

int write(uint32_t v, FILE *f) 
{ 
    return fwrite(&v, sizeof(v), 1, f); 
} 

這將寫正是 32位寬的整數,然後返回實際寫入的字節數。另外,它是可重用的。

接下來,我們可以創建一個方便的複合函數,如果我們想:

int writeLittleEndian(uint32_t v, FILE *f) 
{ 
    return write(toLittleEndian(v), f); 
}