Solidity

bytes32 中的字節與 bytes 結構中的字節之間的區別

  • February 5, 2021

可以在文件中閱讀:

Abytes類似於byte[],但它被緊緊地封裝在呼叫數據和記憶體中。

這到底是什麼意思?例如,根據此連結,我們為什麼要使用以下方法將bytes對象轉換為bytes32

function bytesToBytes32(bytes b, uint offset) private pure returns (bytes32) {
 bytes32 out;

 for (uint i = 0; i < 32; i++) {
   out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
 }
 return out;
}

並且不使用:

function bytesToBytes32(bytes b, uint offset) private pure returns (bytes32) {
 bytes32 out;

 for (uint i = 0; i < 32; i++) {
   out[i] = b[offset + i];
 }
 return out;
}

此外:

  1. 為什麼不能bytes32單獨設置結構的元素,但可以使用bytes
  2. 如果我想通過將字節(字面意思是字節,而不是類型bytes)視為 來對它們進行一些計算,uint8那麼它是否可以通過簡單地轉換為兩種結構來b[i]工作uint8(b[i])?例如,為了uint256從這些類型中獲取一個,可以使用以下程式碼:
uint res;

for (uint i = 0; i < 32; i++) {
   res += uint8(b[i]) * (256 ** i);
}

工作,是b一個對bytes像還是bytes32一個?最後,是uint res = uint(b[i]);uint res = uint(uint8(b[i]));兩個等價的程式碼嗎?

EVM 的基本工作單元,通常稱為一個字,是 32 字節。這意味著對於 EVM,無論我們要表達 1 還是 2^150,都需要 32 個字節或 256 位來完成。

EVM 中的所有內容都需要消耗氣體,包括記憶體,因此單詞越少越好。

一個字節類似於字節

$$ $$,但它被緊緊地包裝在 calldata 和 memory 這到底是什麼意思?

在這裡,緊密打包意味著不是每個項目使用一個單詞(32 字節),而是編譯器將“打包”多個項目以共享一個單詞。

讓我們看一個例子。假設我們要將數字 12345 表示為字節,這給出

$$ 48, 57 $$大端(48 * 16^2 + 57 = 12345)。如果我們不打包字節,這會給我們: $$ 48, 0,…31 times, 57, 0,…31 times $$ 現在,如果我們打包字節,我們可以將其表示為: $$ 48, 57, 0,…30 times $$ 如您所見,使用打包表示減少了我們需要使用的單詞數量。字節尤其如此,因為我們在沒有打包的情況下每個字浪費了 31 個字節。

為什麼不能單獨設置 bytes32 結構的元素,但可以使用字節?

我認為這更像是 Solidity 開發人員的設計選擇,而不是其他任何東西。我不完全確定它背後的基本原理,但我可以想像這bytes32主要是為了保存短字元串並使它們不可變允許一些優化,否則這些優化可能會很乏味。

考慮到這一點,使用的程式碼片段out[i] = b[offset + i]理論上可以工作,但根本不是有效的 Solidity 程式碼。

第一個片段有效,但我認為有點尷尬。b

$$ offset + i $$是一個字節,所以用它來屏蔽它0xff是一個空操作。該行可以簡單地寫成

out |= bytes32(b[offset + i]) >> (i * 8);

我很確定這在語義上是等效的,但如果我遺漏了什麼,請糾正我。

請注意,此轉換與是否打包的字節並不真正相關。

如果我想通過將它們視為 uint8 來對字節(字面意思是字節,而不是類型字節)進行一些計算,那麼它是否可以通過簡單地轉換 b 來適用於這兩種結構?

$$ i $$到 uint8(b$$ i $$)

是的,uint8 和一個字節都代表 8 位數據並且具有相同的範圍,所以這應該沒有任何問題。

最後,是 uint res = uint(b

$$ i $$); 和 uint res = uint(uint8(b$$ i $$)); 兩個等效程式碼?

理論上兩者應該是等價的,但 Solidity 編譯器,至少在目前版本中,不允許將字節uint直接轉換為 a,因此需要顯式轉換為uint8

引用自:https://ethereum.stackexchange.com/questions/86772