Solidity值类型与各种图解

区块链中级.以太坊开发
From:JamesZou & 传智播客研究院 & 传智播客区块链

本文参考文档官方中文文档官方英文文档

一.值类型和引用类型

1.值类型

  • 值类型 是指变量在赋值过程中是将数据完整的拷贝一份,再赋值给新的变量,这种方式需要开辟新的内存空间,效率较低,两个变量完全独立,修改一个不会影响另外一个。
    • 布尔(Booleans)
    • 整型(Integer)
    • 地址(Address)
    • 定长字节数组(fixed byte arrays)
    • 有理数和整型(Rational and Integer Literals,String literals)
    • 枚举类型(Enums)
    • 函数(Function Types)

思考:下面这个代码中的 luckNum 最后等于多少?

pragma solidity ^0.4.25;
contract ValueType{
    function testValueType() public view returns(uint){
        uint luckNum = 101;
        uint loveNum = luckNum;
        changeValue(luckNum);
        return luckNum;
    }
    
    function changeValue(uint _num) private{
        _num += 100;
    }
}

在这里插入图片描述

2.引用类型

  • solidity没有指针,对于复杂的结构进行高效传递方式是使用关键字storage进行修饰。
  • 复杂类型,占用空间较大的。在拷贝时占用空间较大。所以考虑通过引用传递。常见的引用类型有:
    • 字符串(string)
    • 不定长字节数组(bytes)
    • 数组(Array)
    • 结构体(Structs)

二.数据类型

1.值类型详介

1.1 布尔

bool flag1 = true;
bool flag2 = false;

1.2 整型

  • int(有符号整型,有正有负)

  • uint(无符号整型,无负数)

  • 以8位为区间,支持int8,int16,int24 至 int256,uint同理。

    int默认为int256,uint默认为uint256

function intTest() public  returns(int){
	int8 i = 10; 
	int j = 10; 

	return i + j;
}  

1.3 地址

1.3.1 概念
  • 以太坊地址的长度,大小20个字节,每个字节8位,20 * 8 = 160位,所以可以用一个uint160编码。地址是所有合约的基础,所有的合约都会继承地址对象,通过合约的地址串,调用合约内的函数。
1.3.2 运算符
描述 符号
比较运算符 <=,<,==,!=,>=,>
1.3.3 操作
属性/方法 含义 备注
balance(uint256) 获取余额(wei) 属性,其余的都是方法
transfer(uint256 value) 给 address 转账 value(Wei),失败会抛异常 建议使用
send(uint256 value) 和 transfer 类似,transfer 更常用,失败会返回false 不建议使用
call 合约内部调用合约
delegatecall 调底层代码,别用
callcode 调底层代码,别用

在这里插入图片描述

  • call 是一个底层的接口,用来向一个合约发送消息,也就是说如果你想实现自己的消息传递,可以使用这个函数。函数支持传入任意类型的任意参数,并将参数打包成32字节,相互拼接后向合约发送这段数据。
pragma solidity ^0.4.25;
contract Lover{
    string outerMsg;
    function(){
        outerMsg = string(msg.data);
    }
    function getFail() returns (string){
        return outerMsg;
    }
}
contract CallLover{
    function callData(address addr) returns (bool){
        return addr.call("i love Ether ~~!");
    }
}
  • call与delegatecall的功能类似,区别仅在于后者仅使用给定地址的代码,其它信息则使用当前合约(如存储,余额等等)

注意:在 solidity 源码中,address 不需要加双引号。但在 Remix 的对话界面中输入 address 时,务必加上双引号,否则会报错

1.3.4 余额
  • 返回指定地址的余额
pragma solidity ^0.4.25;

contract addressTest{
   function getBalance(address addr) constant public returns  (uint){
       return addr.balance;
   }
}	
  • 合约地址 (this)

    如果只是想返回当前合约账户的余额,可以使用this指针,this表示合约自身的地址

pragma solidity ^0.4.0;

contract addressTest{
    function getBalance() constant public returns  (uint){
        //return addr.balance;
        return this.balance; // <<----此处使用this代替
    }
}
  • 转账(send,transfer)

    send和transfer函数提供了由合约向其他地址转账的功能。

对比项 send transfer 备注
参数 转账金额 转账金额 wei单位
返回值 true/false 无(出错抛异常) transfer更安全
pragma solidity ^0.4.25;

contract TransferTest {
    function transfer123(address addr) payable {
    	addr.transfer(msg.value);
    }
}
  • call 方法 (略)

1.4 字节数组

1.4.1 定长字节数组
  • solidity内置了一些数组的数据类型:(和go语言做一下对比, var [8] byte),完全只读

    • bytes1, … ,bytes32,允许值以步长1递增。
    • byte默认表示bytes1,byte是类型,bytes是类型,bytes1是内置数组
    • bytes1只能存储1个字节,即8位的内容,bytes2最多只能存储2个字节,即16位的内容。以此类推…
    • 长度可以读取 length
    • 长度不可以修改
    • 可以通过下标访问
    • 内容不可修改
  • 内置方法:length() -> 返回数组长度

  • 存储方式:16进制ascii码

pragma solidity ^0.4.25;

//bytes1
contract fixedArray {
    /*
    1. 长度可以读取 length
    2. 长度不可以修改
    3. 可以通过下标访问
    4. 内容不可修改   
    */
    //bytes1 ... bytes32
    
    //bytes1 b1 = "xy";
    bytes2 b2 = "xy";
    
    bytes3 public b3 = "xy";
    
    uint public len = b3.length;
    
    //b3.length = 10;
    
    bytes8 b8 = "12345678";
    
    //b8_0返回0x31,即十进制的数字1的ascii值(3*16+1=49)
    bytes1 public b8_0 = b8[0];
    
    //b = "HELLO";ERROR,定义之后不可修改
    //b8[1] = "0";
    //b8= "4567";
}
  • 运算符支持
描述 符号
比较运算 <=,<,==,!=,>=,>
位运算符 &,|,^(异或),~非
下标访问 [0,n),n表示长度
1.4.2 不定长字节数组
  • bytes:不定长度的字节数组 (Dynamically-sized byte array)

    bytes类型可以使用 push() 方法,具有 length 属性

string public name = "itheima.com";
bytes public g = 0x6c697975656368756e;
// 初始化一个两个字节空间的字节数组
bytes public name = new bytes(2);
  • string: 动态长度的UTF-8编码的字符类型(非值类型),它其实是一个特殊的可变字节数组
string public str01 = "itheima.com";
  • solidity中字符串不像JS中那样,没有length()方法,须转换成字节数组才能使用length属性来获得长度
function getStrLegnth(string _str) constant returns (uint) {
	return bytes(_str).length;  // 强制转换string为bytes
}
  • 一个好的使用原则是:
    bytes用来存储任意长度的字节数据,string用来存储任意长度的UTF-8编码 的字符串数据。
    如果长度可以确定,尽量使用定长的如byte1到byte32中的一个,因为这样更省空间。

1.5 枚举类型

  • 枚举类型是在Solidity中的一种用户自定义类型。
  • 枚举可以显示的转换与整数进行转换,但不能进行隐式转换。显示的转换会在运行时检查数值范围,如果不匹配,将会引起异常。
  • 枚举类型应至少有一名成员,枚举元素默认为uint8,当元素数量足够多时,会自动变为uint16,第一个元素默认为0,使用超出范围的数值时会报错。
pragma solidity ^0.4.0;

contract test {
   
    enum WeekDays {
        Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
    }
    
    WeekDays currentDay;
    WeekDays defaultday = WeekDays.Sunday;
    
    function setDay(weekDays _day) public {
        currentDay = _day;
    }
    
    function getDay() public view returns(uint256) {
        return uint256(currentDay);
    }
    
    function getDefaultDay() public view returns(uint256) {
        return uint256(defaultday);   
    }
}

1.6 函数类型

1.6.1 函数修饰符
  • 函数类型也就是我们所说的函数,本身也是一个特殊的变量,它可以当做变量赋值当做函数参数传递当做返回值

在这里插入图片描述

修饰符 说明
public 公有,任何人(拥有以太坊账户的)都可以调用
private 私有, 只有智能合约内部可以调用
external 仅合约外部可以调用,合约内部需使用this调用
internal 仅合约内部和继承的合约可以调用
view/constant 函数会读取但是不会修改任何contract的状态变量
pure 函数不使用任何智能合约的状态变量
payable 调用函数需要付钱,钱付给了智能合约的账户
returns 返回值函数声明中使用

注意,所有在合约内的东西对外部的观察者来说都是可见,将某些东西标记为private仅仅阻止了其它合约来进行访问和修改,但并不能阻止其它人看到相关的信息。

1.6.2 匿名函数
  • 一个合约可以有且只有一个匿名函数,此函数不能有参数,也不能有任何返回值,当我们企图去执行一个合约上没有的函数时,那么合约就会执行这个匿名函数。

    当合约在只收到以太币的时候,也会调用这个匿名函数,而且一般情况下会消耗很少的gas,所以当你接收到以太币后,想要执行一些操作的话,你尽可以把你想要的操作写到这个匿名函数里,因为这样做成本非常便宜。

//如果想向合约转账,在合约中添加如下函数即可
function() payable {
    //函数体什么都不填
}

区块链接口设计和调用介绍

在这里插入图片描述

POS挖矿机制

在这里插入图片描述

ERC20代币的图解

在这里插入图片描述

编译源码

在这里插入图片描述

合约部署图解

在这里插入图片描述

引用类型传参和值类型传参

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/www294993741/article/details/83793642