你是否知道大端小端的概念,其定义了是高位数据先保存还是地位数据先保存,EVM 是用 大端格式存储数据,我们知道 EVM 使用 32 字节的字来处理数据,当数据不足 32 个字节时,如何填充数据呢?bytes 有哪些操作详见本文。
无论是使用固定大小的bytesN
还是动态大小的bytes
数组,bytes 都是Solidity的一个重要方面。我们将在本文中了解它们的区别、与固定大小数组 bytesN
相关的位操作,并使用它们执行一些通用方法,如连接。
在计算机中,术语 "端"(endianness)用来说明数据的低位字节的存储和排序方式。因此,它定义了计算机或机器存储的内部排序。
我们所说的多字节数据类型数据是指类型(如 uint、float、string等......),在计算机中,多字节数据类型有两种排序方式:小端格式或大端格式(其中格式=顺序)。
在大端格式下,多字节数据类型二进制表示的第一个字节先存储(高位字节先保存)。
使用小端格式时,先存储多字节数据类型二进制表示的最后一个字节。(英特尔 x86 计算机)
如:值为 0x01234567
(十六进制表示法)的变量,在两个格式下的存储是这样的:
<p align="center">两种格式下的存储方式</p>
以太坊和 EVM 是一种使用 大端格式 的虚拟机。在 EVM 中,所有数据(无论其 Solidity 类型如何)都以大端格式存储在虚拟机内部。最重要的是,EVM 使用 32 字节的字来处理数据。
然而,根据其类型(bytesN
、uintN
、address
等......),数据的布局有所不同。数据如何布局
指的是高阶位数据如何放置。
在以太坊和 Solidity 开发者社区中,这被称为填充规则:左填充与右填充。
以下是Solidity中使用的填充规则:
string
, bytes
和 bytesN
.intN
/ uintN
(有符号/无符号整数)、 address
和其他类型。注意:你还会发现 "左对齐"或 "右对齐 "的说法。
为了更好地澄清和避免混淆:
左填充 = 右对齐
右填充 = 左对齐
例如,Solidity 中的 string value = "abcd"
字符串将被 EVM 填充为一个完整的 32 字节, 0 填充在右侧。
0x6162636400000000000000000000000000000000000000000000000000000000
相反,Solidity 中的数字 uint256 value = 1_633_837_924
(= 0x61626364
十六进制)被 EVM 填充为一个完整的 32 字节时。0 将被填充在左边:
0x0000000000000000000000000000000000000000000000000000000061626364
学习数据布局和填充规则对于了解如何在 Solidity 中处理不同的数据类型非常重要。尤其是在处理 bytesN
和它们的 uintN
相关类型时。例如,对于 bytes1
和 uint8
值,即使它们具有相同的位大小,其内部表示也是不同的。请看下面的代码片段。
// 0x00000000…01
Uint8 a = 1;
// 0x01000000….
byte b = 1;
bytes1 c =
本文主要讨论 bytesN
和 bytes
类型。Solidity 提供了两种字节类型:
bytesN
bytes
,表示字节序列。可以使用关键字 bytesX
来定义变量,其中 X
代表字节数。X
可以从 1 到 32
byte
是 bytes1
的别名,因此存储的是单字节。
如果可以将长度限制在一定的字节数,请务必使用 bytes1 至 bytes32 中的一个,因为它们更便宜。
具有固定大小变量的字节可以在合约之间传递。
这是一种非常特殊的类型。基本上,bytes
和 string
是特殊的数组(参见 Solidity 文档)
bytes
来表示任意长度的原始字节数据
在 Solidity 中,术语 bytes
表示字节动态数组。它是 byte[]
的简写。
在 Solidity 代码中,bytes
被视为数组,因此它的长度可以为零,你也可以在它的末尾添加一个字节。
然而,bytes
并不是一个值类型!
若是任意长度的字符串(UTF-8)数据使用字符串。
bytes32 someString = "stringliteral";
该字符串常量量分配给 bytes32 类型时,将以原始字节形式解释。
但是,字符串不能在合约之间传递,因为它们不是固定大小的变量。
Solidity 本身没有字符串操作函数(除了 concat
),但第三方字符串库可以使用。
本节大部分内容基于以下作者的文章Maksym
Solidity 支持基本的位操作(虽然缺少一些,如左移右移),幸好有算术相等。下面将介绍一些位操作的基本原理。
以下用于字节的比较运算符的值为 bool
值: true
或 false
。
<=, <, ==, !=, >=, >
Solidity 中提供了以下位运算符: &
(与), |
(或), ^
(异或) 和 ~
(非).
为简单起见,我们将对两个变量使用 bytes1
数据类型(等于 byte
):a
和b
。我们将在 Solidity 中使用它们的十六进制表示法来初始化它们。
bytes1 a = 0xb5; // [10110101]
bytes1 b = 0x56; // [01010110]
下表显示了它们的二进制格式。
注: 输入为白色背景,结果将以黄色高亮显示
让我们来看看 :
&
(与) : 两个位都必须是 1(白色行),结果才为 true(1 => 黄色行)。
a & b; // Result: 0x14 [00010100]
|
(或) : 至少...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!