在 Solidity 中,bytes 和 bytes32 都是用来保存二进制数据 的类型,但它们的长度、使用场景、Gas 成本完全不同。
✅ 一句话区分
| 类型 | 一句话总结 |
|---|---|
bytes32 |
定长 32 字节,适合做哈希、地址、标识符等固定长度数据。 |
bytes |
动态长度字节数组,适合任意长度数据(如字符串、序列化数据)。 |
📌 对比表
| 特性 | bytes32 |
bytes (bytes memory / bytes calldata) |
|---|---|---|
| 长度 | 固定 32 字节 (256 位) | 动态长度,可以是 0~任意长度 |
| 存储位置 | 可作为 storage / memory / calldata |
多为 memory 或 calldata(不能是 storage 直接存储) |
| Gas 成本 | 极便宜(固定大小) | 随长度线性增加(32 字节为一个 slot) |
| 可变性 | 不可变(定长) | 可变(动态数组) |
| 常见用途 | 哈希值、地址、UUID、枚举键 | UTF-8 字符串、序列化数据、签名、IPFS 哈希 |
| 与字符串互转 | bytes32 <=> string 需手动转换 |
bytes 与 string 可强制转换 |
✅ 代码示例
1. bytes32 用法
solidity
bytes32 public constant ROLE_ADMIN = keccak256("ROLE_ADMIN");
function getHash(string memory text) public pure returns (bytes32) {
return keccak256(abi.encodePacked(text)); // 返回 bytes32
}
2. bytes 用法
solidity
function concat(string memory a, string memory b)
public
pure
returns (string memory)
{
return string(abi.encodePacked(a, b)); // 先转 bytes 再转 string
}
3. 二者互转
solidity
// bytes32 -> bytes
bytes32 data = keccak256("hello");
bytes memory b = abi.encodePacked(data);
// bytes -> bytes32(必须保证长度 ≤ 32)
bytes memory b = "hello";
bytes32 data;
assembly {
data := mload(add(b, 32)) // 手动加载前 32 字节
}
✅ 何时用哪个?
| 场景 | 推荐类型 |
|---|---|
哈希值 (如 keccak256 结果) |
bytes32 |
地址 (如 address 转 bytes) |
bytes32 |
| UTF-8 字符串(不定长) | string 或 bytes |
| ABI 编码数据 | bytes memory |
| 签名数据(>= 65 字节) | bytes |
✅ 一句话总结
bytes32:定长、省 gas,存哈希、存标识符bytes:动态长度,存任意二进制或字符串数据