详述Solidity数据类型之一:值类型

作者:梁雁明

著权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Solidity是一种静态类型语言,也就意味着,每一种变量的类型(状态或局部变量)需要在编译期间被确定。Solidity提供了一些基本数据类型,可以用于构建复杂类型。

补充说明,数据类型可以在包括操作符的表达式中相互转化,详情见:Order of Precedence of Operators

值类

因为这些类型的变量总是通过值传递,所以以下类型被称为值类型,也就是说,在函数参数或者是赋值操作时,他们都会被复制。

Booleans

bool:可取值常量是 true  false.

操作符:

·       ! (逻辑)

·       && (逻辑, "and")

·       || (逻辑, "or")

·       == (等于)

·       != (不等于)

|| && 操作适应于短路规则,也就是说在表达式 f(x) || g(y)中,如果 f(x)  true, g(y) 不会再执行运算,即使有其它影响。

Integers

int / uint:范围不同的有符号和无符号整形类型。以 8 为步长uint8  uint256 关键字(unsigned of 8 up to 256 bits) int8  int256与此类似. uint int 分别是uint256 int256的别名.

操作:

·       运算: <=, <, ==, !=, >=, > (返回 bool

·       位操作: &, |, ^ (与 或 非), ~ ()

·       运算: +, -一元-一元+, *, /, % (取余), ** (), << (左位移), >> (右位移)

除法操作往往会对产生数字片断(除法被编译成EVM里的 DIV 操作码),但如果常量数据的话,是不会进行截取的,例如5/2不等于2而是等于 2.5

 

0除或者以0取余都会导致异常。                                   

位移操作的结果类型是左操作数的类型。表达式 x << y 等于 x * 2**yx >> y 等于 x / 2**y.也就意味着,对负数进行位移会导致越位且负数位移会导致运行时异常。

警告

对有符号的负数进行右位移操作的结果与其它编程语言是不同的。在Solidity中,右位移操作会映射成除法,所以被位移的数值会渐渐转化为0。在其它编程语言中,负数的右移位操作与以四舍五入式的除法很类似(趋向于负无穷大)。

固定点位数字

警告

固定点位数字还没有被Solidity完全支持,固定点位数字可以被声明,但是不能被分配,也不能被指向到。

fixed / ufixed有符号和无符号不同范围的固定点数数字,关键字ufixedMxN fixedMxN其中M 代表类型的整数有效位数,N 代表了小数有效位数. M必须能够被8整数而且范围从8256. N的范围必须是从080,包括80. ufixed fixed 分别是 ufixed128x19 fixed128x19的别名.

操作:

·       运算: <=, <, ==, !=, >=, > (evaluate to bool)

·       运算: +, -一元-一元+, *, /, % (取余)

注解

浮点类型(float double在很多语言中,更加精准的IEEE 754标准数字)与固定点数数字的最主要不同在于:整数位与小数位部分的位数在前者更加灵活,而在后者是严格定义的。通常来说,在浮点数中,几乎全部的空间被用来表示数值,然而只有少数bit用来表示小数点位。

地址

address: 20字节(160位)值(以太坊地址的大小).地址类型也有一些成员变量,地址是所有智能合约的服务基础。

操作:

·       <=, <, ==, !=, >= and >

注解

从智能合约0.5.0版本之后,没有地址类型address, 却仍可以被显示转化成地址类型。

地址的成员变量

·       balance transfer

For a quick reference, see Address Related.

可以通过属性balance 去查询该地址上的余额信息,也可以通过使用 transfer 方法发送EtherAddress地址上:

address x = 0x123;
address myAddress = this;
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);

注解

如果x是一个合约地址它的代码(更明确一些它的回滚方法如果具有此方法会和transfer 方法一起被调用(这是EVM的特性且不能被阻止). 如果执行过程gas用光或因其它问题出错,Ether转账操作会恢复初始状态,当前合约会以抛出异常的方式结束执行。

·       send

send方法是与transfer功能相似。如果执行失败,当前合约同样以异常方式结束执行,但send 方法会返回 false

警告

在使用send方法时会有一些危险如果堆栈调用深度达到1024时,转账会失败,(实施者往往可以强制实现此过程),或当接受者gas用光时,也会导致转账失败.所以为了安全进行Ether转账, 请多检查send方法的返回值使用transfer方法也许会更好使用一种可以让接收者可以返还Ether的模式。

·       call, callcode delegatecall

而且,为了使智能合约交互不依附于ABI(应用程序二进制接口),方法call 被提供,以包含任意类型、任意长度的参数,这此参数被整合在32个字节的空间中并被整合连接起来。当第一个参数被准确的编码为4字节时,会导致异常,在这种情况下,不会允许使用签名功能。

nameReg.call(bytes4(keccak256("fun(uint256)")), a);

call 方法返回boolean,用以区别被调用的功能是以(true执行成功结束或者是以EVM 异常(false)结束运行直接访问实际的返回数据是不可能的(如果这样的话,我们需要提前知道其编码和大小).

可以通过调用.gas() 方法来调整gas供应:

namReg.call.gas(1000000)("register","MyName");

同样地以太币的数量也可以被调整:

nameReg.call.value(1ether)("register","MyName");

最后,以上两种调整方法可以进行合并,其中顺序并不重要:

nameReg.call.gas(1000000).value(1ether)("register","MyName");

注解

仍然不能在负载的方法上使用gasvalue的修改方法。

引入工作区的概念,是为了以处理gasvalue特殊情况,以重新检查他们是否存在于重载节点。

 

相同地也可以使用delegatecall方法:区别是,只有给定地址的代码会被使用,而其它方面(storage, balance, ...)会从当前合约中去除delegatecall 的目的是调用存储在另一个合约中的库代码使用者必须确保两合约的存储布局合理以便delegatecall方法可被使用。在homestead之前只有名叫callcode 的限制版本是可用的,并不提供可以访问到原始msg.sender msg.value.

所有 call, delegatecall callcode 这三个功能,都是low-level的方法,当打破Solidity的类型安全时,它们作为一种最终手段被调用(怎么听起来有点悲壮)。

.gas() 是所有的三个方法中都是有效的然而 .value() delegatecall中是不被支持的。

注解

所有合约都继承地址成员,所以可以通过this.balance

本文由 区块链技术网 作者:区块链 发表,其版权均为 区块链技术网 所有,文章内容系作者个人观点,不代表 区块链技术网 对观点赞同或支持。如需转载,请注明文章来源。

发表评论