Solidity 动态字节数组
前面介绍了静态字节数组,它的长度是固定的,而且最长也就只有32字节。那么如果我们希望存放超过32个字符怎么办。又或者我们希望它的长度可以变化的,可以按需增加的。这个时候我们就可以使用动态字节数组(dynamically-sized byte array)。动态字节数组其实是数组类型(array)其中的一种类型,只不过是字节数组而已。我们单独抽出来介绍是想要跟静态字节数组做对比。
特别注意动态字节数组是引用类型(reference type),而静态字节数组是值类型(value type)
动态字节数组与静态字节数组的区别
动态字节数组与静态字节数组有几点区别:
- 静态字节数组长度是固定的,在编译期就已经确定;而动态字节数组的长度是不固定的
- 静态字节数组的长度只能是1到32字节;而动态字节数组没有长度的限制
- 动态字节数组是引用类型(reference type),也就是说其变量存储的其实是数组的地址;而静态字节数组是值类型(value type)
如果一个字节数组已经明确长度不会发生改变,而且长度小于等于32字节,那么建议使用静态字节数组。会更高效,更节省Gas。其他情况才推荐使用动态字节数组。
动态字节数组的种类
Solidity有两种动态字节数组:
- bytes
- string
其中 bytes
类似于 bytes1[]
不过 bytes
在 memory
和 calldata
位置会更加紧凑。Solidity 的存储结构里面规定了 memory
和 calldata
中的数组(比如bytes1[]
)的每个元素都要占据32字节的倍数。不足32字节的,会自动 padding 到32字节。但是对于 bytes
和 string
没有这样的要求。所以 bytes
和 string
会比 bytes1[]
更加紧凑。
string
的内部结构基本等同于 bytes
的类型,但是它不能进行下标访问,也不能获取长度。换种说法就是 string
和 bytes
内部存储结构相同,但是对外访问接口不同。
bytes与string的互相转换
bytes和string类型之间可以相互转换。需要用到:
bytes(str)
: 显式地将string转换成bytesstring(myBytes)
: 显式地将bytes转换成string
bytes
转 string
bytes memory bstr = new bytes(10);
string memory message = string(bstr); // 使用string()函数转换
string
转 bytes
string memory message = "hello world";
bytes memory bstr = bytes(message); //使用bytes()函数转换
string 不能进行下标访问,也不能获取长度
虽然 string
也是数组但是目前还不支持它的下标访问和长度的获取。
string
不能进行下标访问,也不能获取长度string str = "hello world";
uint len = str.length; // 不合法,不能获取长度
bytes1 b = str[0]; // 不合法,不能进行下标访问
你可以将 string
转换成 bytes
后再进行下标访问和获取长度
string
转换成 bytes
后再进行下标访问和获取长度string str = "hello world";
uint len = bytes(str).length; // 合法
bytes1 b = bytes(str)[0]; // 合法