這個函數據說做的是寫一個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);
}
這在小尾數格式寫入文件的32位無符號整數。 –
檢查寫入文件的函數時出錯。在甚至有用的錯誤檢查很少見的世界中罕見的發現。 – user3386109
後續問題(適用於所有人):你可以在不使用評論的情況下編寫可讀的*嗎? – TobiMcNamobi