solidity基础-引用类型
数据和变量
- Solidity 是一种静态强类型的语言
- 变量类型和需要赋值的数据类型必须匹配,或者所赋值的数据可以隐式转换为变量类型
两种类型的数据
值类型
- 值类型传值时会将值拷贝一份,传递的是值本身
- 始终按值来传递
引用类型
- 引用类型进行传递时,传递的是其指针
- 引用类型进行传递时,可以为值传递,也可以为引用传递
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
uint256 public u = 123;
string public str1 = "b00l";
string public str2 = "b00l";
function test() external {
// 修改值类型
uint256 x = u;
x = 1;
// 修改引用类型,引用传递
string storage str3 = str1;
bytes(str3)[0] = bytes1("B"); // str1 的值变为 B00l
// 修改引用类型,值传递
string memory str4 = str2;
bytes(str4)[0] = bytes1("B"); // str2 的值不变
}
}
引用类型
Array
- 创建
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
// 固定长度数组创建
uint256[5] public arrInt = [1, 2, 3, 4, 5]; // [1, 2, 3, 4, 5]
uint256[5] public arrInt2 = [1]; // [1, 0, 0, 0, 0]
address[1] public arrAddress = [0x5B38Da6a701c568545dCfcB03FcB875f56beddC4];
uint256[5] public arrInt3;
// 可变长度数组
uint256[] public arrInt4 = [1, 2, 3, 4, 5]; // 不能在函数内创建
uint256[] arrInt5 = new uint256[](5); // 可以在函数内创建,如果 memory 的时候,不能用 push 方法
// 内存中创建数组
function test1() public pure returns (uint256[] memory) {
uint256[] memory arrInt6 = new uint256[](5);
arrInt6[0] = 1;
return arrInt6;
}
// 二维数组的创建
uint256[2][2] public arrInt7 = [[1, 2], [3, 4]];
}
动态数组比定长数组更废 gas
- 访问和修改数组元素
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
uint256[] arr = [1, 2, 3];
function test1() external view returns (uint256) {
return arr[0];
}
function test2() external {
arr[0] = 2;
}
}
- 函数中返回整个数组
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
uint256[] arr = [1, 2, 3];
function test1() external view returns (uint256[] memory) {
return arr;
}
}
- 数组常量
数组的属性
- length:获取数组长度(只读)
数组的方法
- push
- pop
- delete,用在数组元素表示重置数组元素,长度不变。用在整个数组表示将数组长度置为零
- name[n: m]:切片
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
uint256[] arr = [1, 2, 3];
function getArr() external view returns (uint256[] memory) {
return arr;
}
function testPush() external {
arr.push(9);
}
function testPop() external {
arr.pop();
}
function testDel1() external {
delete arr[0];
}
function testDel2() external {
delete arr;
}
}
- 模拟切片的 slice 方法
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
function slice(
uint256[] memory arr_,
uint256 begin,
uint256 end
) public pure returns (uint256[] memory) {
require(begin < end, "index error");
uint256[] memory tmp = new uint256[](end - begin);
for (uint256 index = begin; index < end; index++) {
tmp[begin - index] = arr_[index];
}
return tmp;
}
function test() external pure returns (uint256[] memory res) {
uint256[] memory arr = new uint256[](5);
res = slice(arr, 1, 2);
}
}
- delete 完全删除数组的指定索引
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
function deletePro(uint256[] memory arr_, uint256 index_)
internal
pure
returns (uint256[] memory tmp)
{
require(index_ < arr_.length, "index error");
tmp = new uint256[](arr_.length - 1);
for (uint256 i = 0; i < tmp.length; i++) {
if (i >= index_) {
tmp[i] = arr_[i + 1];
} else {
tmp[i] = arr_[i];
}
}
}
uint256[] arr = [1, 2, 3, 4, 5];
function test() external view returns (uint256[] memory) {
return deletePro(arr, 1);
}
}
bytes
- 创建
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
// 方式一
bytes public test1 = bytes("b00l"); // 0x6230306c
// 方式二
bytes public test2 = hex"6230306c"; //0x6230306c
// 方式三
bytes public test3 = new bytes(2); // 0x0000
// 方式四 在函数内部创建
function fun1() external pure returns (bytes memory) {
bytes memory tmp = new bytes(2);
return tmp; // 0x0000
}
}
bytes / bytes32 / bytes32[] 的区别
- bytes:可变字节数组,引用类型
- bytes32:固定长度字节数组,值类型
- bytes32[]:由固定长度字节数组组成的数组
属性
- length:获取长度
- name[index]:获取指定index下标的数据
方法
- contact:拼接bytes,返回值是bytes
- push
- pop
- delete
- name[n, m]:切片
string
格式
- 成对双引号或单引号包裹
属性
- 长度:注意,要先转成bytes类型才可获取长度
- 索引:需要先转成bytes才能获取指定索引的值
- string 和 bytes / bytesN 之间的转换
bytes 转 string
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
bytes public bt1 = bytes("b00l"); // 6230306c
bytes4 public bt2 = bytes4("b00l"); // 6230306c
// 动态大小字节数组 => string
function trans1() external pure returns (string memory) {
bytes memory bstr = new bytes(2); // 函数内构建
bstr[0] = "a";
bstr[1] = "b";
return string(bstr); // ab
}
// 固定长度字节数组 => [动态大小字节数组] => string
function trans2() external pure returns (string memory) {
bytes4 bstr = 0x6230306c;
bytes memory tmp = new bytes(bstr.length);
for (uint256 i = 0; i < bstr.length; i++) {
tmp[i] = bstr[i];
}
return string(tmp);
}
}
string 转 bytes
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
string str = "b00l";
function trans1() external view returns (bytes memory) {
return bytes(str); // 0x6230306c
}
}
mapping
- 概念:mapping(映射)是一种引用类型,存储键值对。
- 创建
// 创建mapping,第一个 string 约束键的类型,第二个 string 约束值的类型
mapping(string => string) public test;
- 获取-设置-删除
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
// 创建mapping,第一个 string 约束键的类型,第二个 string 约束值的类型
mapping(string => string) m;
// 获取mapping
function getvalue() external view returns (string memory) {
return m["name"];
}
// 设置mapping
function setValue() external {
m["name"] = "b00l";
}
// 删除mapping
function delValue() external {
delete m["name"];
}
}
struct
struct(结构体) 是solidity 中的自定义类型,其中可以包含整型、字符串、映射、结构体等复杂类型
- 创建 struct
struct BaseInfo {
string name;
uint8 age;
}
- 创建实例
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
// 创建struct
struct BaseInfo {
string name;
uint8 age;
}
// 实例化struct
BaseInfo public b00l = BaseInfo("b00l", 18);
// 或者
BaseInfo public b00l = BaseInfo({name: "b00l", age: 18});
}
- 读取、修改、删除
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract Demo {
// 创建struct
struct BaseInfo {
string name;
uint8 age;
}
// 实例化 struct
BaseInfo public b00l = BaseInfo("b00l", 18);
// 实例化 struct
function setStruct() external pure returns (BaseInfo memory) {
BaseInfo memory b00l2 = BaseInfo("b00l2", 20);
return b00l2;
}
// 读取 struct
function getName() external view returns (string memory) {
return b00l.name; // b00l
}
// 修改 struct
function resetStruct() external {
b00l.age = 20;
}
// 删除 struct
function delStruct() external {
delete b00l;
}
}