solidity基础语法(以太坊solidity合约)
- 1-值类型和取值范围
- 2-引用类型
- 3-引用类型高阶
- 4-固定数组和动态数组
1-值类型和取值范围
https://learnblockchain.cn/docs/solidity/introduction-to-smart-contracts.html#subcurrency
https://learnblockchain.cn/docs/solidity/types.html
定长数组是值类型,不定长数组是引用类型
String也是引用类型
字符串、不定长数组及结构体都是引用类型
当部署出现问题等等,但代码无错时,尝试离开网站,再次进入重新编译部署
注意solidity版本
值类型修改_a不会影响到_b,只是值的复制
而引用类型则是会影响的
Demo1和demo2的合约区分类型unit
pragma solidity >=0.4.0 <0.7.0; // 声明solidity的版本
// 创建一个智能合约(合约名第一个字母一般大写)
contract Demo01{
uint _a; //solidity命名规范下划线_a,若直接a,在下面的函数中无法识别变量a
uint _b; // 整型属于值类型,赋值的本质是拷贝数据
// 函数(无返回值,传入i,赋值给_a、_b)
function setAll(uint i) public{
_a = _b = i;
}
//solidity命名规范下划线_a
function setA(uint a) public{
_a = a;
}
// view: 代表当前函数不会修改账本的数据,只读函数,不会修改账本数据,不写也行会有警告
// int uint 大小默认是256
//returns (uint,uint) 具有返回值
function getAB() public view returns (uint,uint){
return (_a,_b);
}
}
contract Demo02{
uint8 _a; // 0~255
int8 _b; // 整型属于值类型,赋值的本质是拷贝数据 -128 ~127
// 函数
function setAll(uint8 a,int8 b) public{
_a = a;
_b = b;
}
function setA(uint8 a) public{
_a = a;
}
// view: 代表当前函数不会修改账本的数据
// int uint 大小默认是256,可以接受unit8的类型(当输入值300则超出unit界限255,int8 128范围)
function getAB() public view returns (uint,int){
return (_a,_b);
}
}
编译成功
值类型修改_a不会影响到_b,只是值的复制
而引用类型则是会影响的
// int uint 大小默认是256
在solidity中unit256,8等等类型
非常多的细微类型,java中硬件便宜,智能合约写的成本很高,所以严格限制写的操作
数据类型大小非常严格
设计使用等非常严格
2-引用类型
https://learnblockchain.cn/docs/solidity/types.html#reference-types
值类型是不断复制
告诉程序,引用类型是存到内存中作为临时变量还是存在状态中作为永久的变量
之前的合约,参数默认存储memery局部变量
内存memary临时的
存储storyge永久的
现在引用,不同的引用类型数据位置相互赋值
多了数据存储位置的概念在solidity
下方重要
pragma solidity >=0.6.1 <0.7.0;
// 1: solidity: 数据类型:值类型,引用类型 (数组、结构体,映射、字符串(bytes数组)
// 2: 值传递是副本,而引用类型既可传递指针,也可传递副本(传递规则受数据位置影响)
// 3: 三种位置,先掌握内存与存储变量
// 1: 内存,局部变量 --> 函数调用完毕后消失
// 2: 状态,全局变量 ---> 随着合约部署到区块链中(以太坊分布式账本)
// 3: 调用数据 (暂时理解成内存变量 略)
// 4: 默认的函数参数,包括返回的参数,他们默认是memory。默认的局部变量是storage。而状态变量肯定是storage(不用指定)
// 5: 不同数据位置的引用类型赋值会创建副本,而相同数据位置引用类型仅仅赋值指针
// 注意:在版本0.5.0之前,数据位置可以省略,在0.5.0之后需要指定
contract RefType{
function modifyName(string memory name) pure public returns(string memory){
// 声明临时string类型的变量
// string memory name1 = name;
// // string是可变量的,但是可以先强转为字符数组
// bytes(name1)[0] = 'J';
string memory name1 = name;
bytes(name)[0] = 'J';
return name1;
}
}
修改name1返回name1,值变了
修改name返回name1则和上面的结果一样
相同的引用类型是指针复制
即传入的string memory name和赋值string memory name1 = name;都是相同的引用类型,是指针赋值
引用类型必须指定数据存储位置,数据存储位置还会影响引用类型之间的赋值
3-引用类型高阶
如果是引用类型,并且它的数据位置是memary,则其传递的是指针,没有产生相应的副本
pragma solidity >=0.6.1 <0.7.0;
//
contract RefType{
// 状态变量 storage (不能修改为内存变量)(此类变量会随着合约的部署存储到分布式账本,后面的众筹的钱就要存到状态变量中
//否则内存变量一旦执行完毕就会消失)
string public _name = "solidity"; //加入的public为访问修饰符,若不加,编译部署后,在左下测无此变量。Public任何的属性和函数都可以访问
function f() public{
modifyName(_name);
}
// public 函数参数和返回数据类型必须为memory
// internal 受保护的函数,仅仅自身合约或者子合约(支持继承)才能被调用
//pure代表不能对当前变量读写所以去掉,下方在进行读写
//下方传入状态变量
//函数中赋值也为状态变量,数据存储位置相同传递的是指针,即更改某个只会影响到另一个值
function modifyName(string storage name) internal{
// storage name --> storage name1 传递的是指针
// string storage name1 = name;
// storage name --> memory name1 传递的是数据的副本
string memory name1 = name;
bytes(name1)[0] = 'S';
}
}
string public _name = "solidity"; //加入的public为访问修饰符,若不加,编译部署后,在左下测无此变量
// 1: solidity: 数据类型:值类型,引用类型 (数组、结构体,映射、字符串(bytes数组)
有些合约需要存储到分布式账本,所以在solidity中不但有数据类型还有数据类型所存的位置,存储位置针对引用类型和值类型无关
// 2: 值传递是副本,而引用类型既可传递指针,也可传递副本(传递规则受数据位置影响)
// 3: 三种位置,先掌握内存与存储变量
// 1: 内存,局部变量 --> 函数调用完毕后消失
// 2: 状态,全局变量 ---> 随着合约部署到区块链中(以太坊分布式账本)
// 3: 调用数据 (暂时理解成内存变量 略)
// 4: 默认的函数参数,包括返回的参数,他们默认是memory。默认的局部变量是storage。而状态变量肯定是storage(不用指定)
// 5: 不同数据位置的引用类型赋值会创建副本,而相同数据位置引用类型仅仅赋值指针
状态变量默认是storyge存储类型的
4-固定数组和动态数组
pragma solidity >=0.6.0 <0.7.0;
// 数组是数据类型, 但更具体的说,它是依赖其它数据类型的数据结构(数组指的是相同类型的数值组)
// Solidity中的数组可以是固定数组或者动态数组
contract ArrDemo{
// 固定数组:声明时预定了大小的数组,而且后期不能修改
uint[5] age;
// 动态数组: 声明时没有预定大小的数组,可以新增元素
//后期商品的众筹,但是平台有多少个商品,初始是不知道的,商品是个复杂结构体
uint[] age2 = [uint(10),20,30,40];
//构造函数
constructor()public{
age = [uint(10),20,30,40];//初始化了4个元素,最后第五个元素未初始化默认零
}
// 通过for + length循环来进行迭代
function sum() public view returns(uint){
uint total = 0;
for(uint i =0;i<age.length;i++){
total += age[i];
}
// 固定数组Length不能修改
// age.length = 10;
return total;
}
// 固定数组可以通过index对数组的值进行操作, 但是不能新增
function setValue(uint index,uint value)public{
age[index] = value;
// 静态数组没有push函数
// age.push(value);
}
function sum2() public view returns(uint,uint){
uint total = 0;
for(uint i =0;i<age2.length;i++){
total += age2[i];
}
// 固定数组Length不能修改
// age.length = 10;
return (total,age2.length); //返回多个值需要括号
}
// 动态数组支持新增操作(length大小是可以扩充的)
function addValue(uint val) public{
age2.push(val);
}
}
数组的遍历数组的更新,对动态数组的添加操作