在某些情況下,編譯器會自動進行隱式類型轉換, 這些情況包括: 在賦值、參數傳遞給函數以及應用運算符時。 通常,如果可以進行值類型之間的隱式轉換, 並且不會丟失任何資訊。 都是可以隱式類型轉換
例如, uint8
可以轉換成 uint16
,int128
可以轉換成 int256
,但 int8
不能轉換成 uint256
(因為 uint256
不能涵蓋某些值,例如-1
)
如果將運算子應用於不同的類型,則編譯器將嘗試將其中一個操作數隱式轉換為另一個操作數的類型(賦值也是如此),這意味著操作始終以操作數之一的類型執行
uint8 y;
// int8 y; cannot because uint32 doesn't cover some value which int8 can.
uint16 z;
uint32 x = y + z;
如果某些情況下編譯器不支援隱式轉換,但是你很清楚你要做的結果,這種情況可以考慮顯式轉換。 注意這可能會發生一些無法預料的後果,因此一定要進行測試,確保結果是你想要的! 下面的範例是將一個int8
類型的負數轉換成 uint
:
int8 y = -3;
uint x = uint(y);
//x的值將是 0xfffff..fd(64 個 16 進位字元),因為這是 -3 的 256 位補碼形式
如果一個類型顯式轉換成更小的類型,相應的高位將被捨棄
uint32 a = 0x12345678;
uint16 b = uint16(a); *// 此時 b 的值是 0x5678*
如果將整數顯式轉換為更大的類型,則將填充左側(即在更高階的位置), 轉換結果依舊等於原來整數
uint16 a = 0x1234;
uint32 b = uint32(a); *// b 為 0x00001234 now* assert(a == b);
定長位元組陣組轉換則有所不同, 他們可以被認為是單個字節的序列和轉換為較小的類型將切斷序列
bytes2 a = 0x1234;
bytes1 b = bytes1(a); *// b 為 0x12*
如果將定長位元組陣列顯式轉換為更大的類型,將按正確的方式填充。 以固定索引存取轉換後的位元組將在和之前的值相等 (如果索引仍然在範圍內):
bytes2 a = 0x1234;
bytes4 b = bytes4(a); *// b 為 0x12340000*assert(a[0] == b[0]);
assert(a[1] == b[1]);
十進位和十六進位字面常量可以隱式轉換為任何足以表示它而不會截斷的整數類型
uint8 a = 12; *// 可行*
uint32 b = 1234; *// 可行*
uint16 c = 0x123456; *// 失败, 會截断為 0x3456*
十進位字面常量不能隱式轉換為定長位元組陣列。 十六進位字面常量可以是,但僅當十六進位陣列大小完全符合定長位元組陣列長度。 不過零值例外,零的十進位和十六進位字面常量都可以轉換為任何定長位元組陣列類型:
bytes2 a = 54321; *// 不可行*
bytes2 b = 0x12; *// 不可行*
bytes2 c = 0x123; *// 不可行*
bytes2 d = 0x1234; *// 可行*
bytes2 e = 0x0012; *// 可行*
bytes4 f = 0; *// 可行*
bytes4 g = 0x0; *// 可行*
字串字元面常量和十六進位字元串字面常量可以隱式轉換為定長位元組陣列,如果它們的字元數與位元組類型的大小相匹配:
bytes2 a = hex"1234"; *// 可行*
bytes2 b = "xy"; *// 可行*
bytes2 c = hex"12"; *// 不可行*
bytes2 d = hex"123"; *// 不可行*
bytes2 e = "x"; *// 不可行*
bytes2 f = "xyz"; *// 不可行*
參考 位址字面常量 ,通過校驗和測試的正確大小的十六進位字面常量會作為 address
類型。 沒有其他字面常量可以隱式轉換為address
類型。
一個位址 address a
可以通過 payable(a)
轉換為 payable
類型