基本類型之間的轉(zhuǎn)換

2022-05-12 17:01 更新

隱式轉(zhuǎn)換

在某些情況下,編譯器會在賦值期間、將參數(shù)傳遞給函數(shù)以及應(yīng)用運(yùn)算符時自動應(yīng)用隱式類型轉(zhuǎn)換。一般來說,如果在語義上有意義并且沒有信息丟失,則值類型之間的隱式轉(zhuǎn)換是可能的。

例如,uint8可轉(zhuǎn)換為 uint16int128int256int8不可轉(zhuǎn)換為uint256,因?yàn)?code>uint256不能保存諸如 之類的值-1。

如果將運(yùn)算符應(yīng)用于不同的類型,編譯器會嘗試將其中一個操作數(shù)隱式轉(zhuǎn)換為另一個操作數(shù)的類型(賦值也是如此)。這意味著操作總是以操作數(shù)之一的類型執(zhí)行。

有關(guān)可以進(jìn)行哪些隱式轉(zhuǎn)換的更多詳細(xì)信息,請參閱有關(guān)類型本身的部分。

在下面的示例中,加法的操作數(shù)yz不具有相同的類型,但uint8可以隱式轉(zhuǎn)換為uint16,反之亦然。因此, 在類型中執(zhí)行加法之前y轉(zhuǎn)換為類型。表達(dá)式的結(jié)果類型是。因?yàn)樗环峙浣o類型的變量,所以在添加之后執(zhí)行另一個隱式轉(zhuǎn)換。zuint16y + zuint16uint32

uint8 y;
uint16 z;
uint32 x = y + z;

顯式轉(zhuǎn)換

如果編譯器不允許隱式轉(zhuǎn)換,但您確信轉(zhuǎn)換會起作用,則有時可以進(jìn)行顯式類型轉(zhuǎn)換。這可能會導(dǎo)致意外行為并允許您繞過編譯器的某些安全功能,因此請務(wù)必測試結(jié)果是否符合您的要求!

舉一個將負(fù)數(shù)轉(zhuǎn)換為 a 的int示例uint

int  y = -3;
uint x = uint(y);

在此代碼片段的末尾,x將具有值0xfffff..fd(64 個十六進(jìn)制字符),在 256 位的二進(jìn)制補(bǔ)碼表示中為 -3。

如果將整數(shù)顯式轉(zhuǎn)換為更小的類型,則高階位被截?cái)啵?/p>

uint32 a = 0x12345678;
uint16 b = uint16(a); // b will be 0x5678 now

如果一個整數(shù)被顯式轉(zhuǎn)換為一個更大的類型,它會被填充到左邊(即在高階端)。轉(zhuǎn)換的結(jié)果將等于原始整數(shù):

uint16 a = 0x1234;
uint32 b = uint32(a); // b will be 0x00001234 now
assert(a == b);

固定大小的字節(jié)類型在轉(zhuǎn)換過程中表現(xiàn)不同。它們可以被認(rèn)為是單個字節(jié)的序列,轉(zhuǎn)換為更小的類型將切斷序列:

bytes2 a = 0x1234;
bytes1 b = bytes1(a); // b will be 0x12

如果將固定大小的字節(jié)類型顯式轉(zhuǎn)換為更大的類型,則會在右側(cè)填充。訪問固定索引處的字節(jié)將導(dǎo)致轉(zhuǎn)換前后的值相同(如果索引仍在范圍內(nèi)):

bytes2 a = 0x1234;
bytes4 b = bytes4(a); // b will be 0x12340000
assert(a[0] == b[0]);
assert(a[1] == b[1]);

由于整數(shù)和固定大小的字節(jié)數(shù)組在截?cái)嗷蛱畛鋾r表現(xiàn)不同,因此僅允許整數(shù)和固定大小的字節(jié)數(shù)組之間的顯式轉(zhuǎn)換,前提是兩者具有相同的大小。如果要在整數(shù)和不同大小的固定大小字節(jié)數(shù)組之間進(jìn)行轉(zhuǎn)換,則必須使用中間轉(zhuǎn)換來明確所需的截?cái)嗪吞畛湟?guī)則:

bytes2 a = 0x1234;
uint32 b = uint16(a); // b will be 0x00001234
uint32 c = uint32(bytes4(a)); // c will be 0x12340000
uint8 d = uint8(uint16(a)); // d will be 0x34
uint8 e = uint8(bytes1(a)); // e will be 0x12

bytes數(shù)組和bytescalldata 切片可以顯式轉(zhuǎn)換為固定字節(jié)類型(bytes1/…/ bytes32)。如果數(shù)組比目標(biāo)固定字節(jié)類型長,最后會發(fā)生截?cái)唷H绻麛?shù)組比目標(biāo)類型短,則將在末尾用零填充。

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.5;

contract C {
    bytes s = "abcdefgh";
    function f(bytes calldata c, bytes memory m) public view returns (bytes16, bytes3) {
        require(c.length == 16, "");
        bytes16 b = bytes16(m);  // if length of m is greater than 16, truncation will happen
        b = bytes16(s);  // padded on the right, so result is "abcdefgh\0\0\0\0\0\0\0\0"
        bytes3 b1 = bytes3(s); // truncated, b1 equals to "abc"
        b = bytes16(c[:8]);  // also padded with zeros
        return (b, b1);
    }
}
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號