智能合约语言 Solidity 教程系列5 - 数组介绍
最新内容会更新在主站深入浅出区块链社区
原文链接:智能合约语言 Solidity 教程系列5 - 数组介绍
写在前面
Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,
如果你还不了解,建议你先看以太坊是什么
本文前半部分是参考Solidity官方文档(当前最新版本:0.4.20)进行翻译,后半部分对官方文档中没有提供代码的知识点补充代码说明(订阅专栏阅读)。
数组(Arrays)
数组可以声明时指定长度,也可以是动态变长。对storage存储的数组来说,元素类型可以是任意的,类型可以是数组,映射类型,结构体等。但对于memory的数组来说。如果作为public函数的参数,它不能是映射类型的数组,只能是支持ABI的类型。
一个元素类型为T,固定长度为k的数组,可以声明为T[k],而一个动态大小(变长)的数组则声明为T[]。
还可以声明一个多维数组,如声明一个类型为uint的数组长度为5的变长数组(5个元素都是变长数组),可以声明为uint[][5]。(注意,相比非区块链语言,多维数组的长度声明是反的。)
要访问第三个动态数组的第二个元素,使用x[2][1]。数组的序号是从0开始的,序号顺序与定义相反。
bytes和string是一种特殊的数组。bytes类似byte[],但在外部函数作为参数调用中,bytes会进行压缩打包。string类似bytes,但不提供长度和按序号的访问方式(目前)。
所以应该尽量使用bytes而不是byte[]。
可以将字符串s通过bytes(s)转为一个bytes,可以通过bytes(s).length获取长度,bytes(s)[n]获取对应的UTF-8编码。通过下标访问获取到的不是对应字符,而是UTF-8编码,比如中文编码是多字节,变长的,所以下标访问到的只是其中的一个编码。
类型为数组的状态变量,可以标记为public,从而让Solidity创建一个访问器,如果要访问数组的某个元素,指定数字下标就好了。(稍后代码事例)
创建内存数组
可使用new关键字创建一个memory的数组。与stroage数组不同的是,你不能通过.length的长度来修改数组大小属性。我们来看看下面的例子:
pragma solidity ^0.4.16;
contract C {
function f(uint len) public pure {
uint[] memory a = new uint[](7);
//a.length = 100; // 错误
bytes memory b = new bytes(len);
// Here we have a.length == 7 and b.length == len
a[6] = 8;
}
}
数组常量及内联数组
数组常量,是一个数组表达式(还没有赋值到变量)。下面是一个简单的例子:
pragma solidity ^0.4.16;
contract C {
function f() public pure {
g([uint(1), 2, 3]);
}
function g(uint[3] _data) public pure {
// ...
}
}
通过数组常量,创建的数组是memory的,同时还是定长的。元素类型则是使用刚好能存储的元素的能用类型,比如[1, 2, 3],只需要uint8即可存储,它的类型是uint8[3] memory。
由于g()方法的参数需要的是uint(默认的uint表示的其实是uint256),所以需要对第一个元素进行类型转换,使用uint(1)来进行这个转换。
还需注意的一点是,定长数组,不能与变长数组相互赋值,我们来看下面的代码:
// 无法编译
pragma solidity ^0.4.0;
contract C {
function f() public {
// The next line creates a type error because uint[3] memory
// cannot be converted to uint[] memory.
uint[] x = [uint(1), 3, 4];
}
}
已经计划在未来移除这样的限制。当前因为ABI传递数组还有些问题。
成员
length属性
数组有一个.length属性,表示当前的数组长度。storage的变长数组,可以通过给.length赋值调整数组长度。memory的变长数组不支持。
不能通过访问超出当前数组的长度的方式,来自动实现改变数组长度。memory数组虽然可以通过参数,灵活指定大小,但一旦创建,大小不可调整。
push方法
storage的变长数组和bytes都有一个push方法(string没有),用于附加新元素到数据末端,返回值为新的长度。
限制情况
当前在external函数中,不能使用多维数组。
另外,基于EVM的限制,不能通过外部函数返回动态的内容。
contract C {
function f() returns (uint[]) { ... }
}
在这个的例子中,如果通过web.js调用能返回数据,但从Solidity中调用不能返回数据。一种绕过这个问题的办法是使用一个非常大的静态数组。
pragma solidity ^0.4.16;
contract ArrayContract {
uint[2**20] m_aLotOfIntegers;
// 这里不是两个动态数组的数组,而是一个动态数组里,每个元素是长度为二的数组。
bool[2][] m_pairsOfFlags;
// newPairs 存在 memory里,因为是函数参数
function setAllFlagPairs(bool[2][] newPairs) public {
m_pairsOfFlags = newPairs;
}
function setFlagPair(uint index, bool flagA, bool flagB) public {
// 访问不存在的index会抛出异常
m_pairsOfFlags[index][0] = flagA;
m_pairsOfFlags[index][1] = flagB;
}
function changeFlagArraySize(uint newSize) public {
// 如果新size更小, 移除的元素会被销毁
m_pairsOfFlags.length = newSize;
}
function clear() public {
// 销毁
delete m_pairsOfFlags;
delete m_aLotOfIntegers;
// 同销毁一样的效果
m_pairsOfFlags.length = 0;
}
bytes m_byteData;
function byteArrays(bytes data) public {
// byte arrays ("bytes") are different as they are stored without padding,
// but can be treated identical to "uint8[]"
m_byteData = data;
m_byteData.length += 7;
m_byteData[3] = byte(8);
delete m_byteData[2];
}
function addFlag(bool[2] flag) public returns (uint) {
return m_pairsOfFlags.push(flag);
}
function createMemoryArray(uint size) public pure returns (bytes) {
// Dynamic memory arrays are created using `new`:
uint[2][] memory arrayOfPairs = new uint[2][](size);
// Create a dynamic byte array:
bytes memory b = new bytes(200);
for (uint i = 0; i < b.length; i++)
b[i] = byte(i);
return b;
}
}
补充事例说明
事例代码及讲解,请订阅区块链技术查看。
参考视频
我们也推出了目前市面上最全的视频教程:深入详解以太坊智能合约语言Solidity
目前我们也在招募体验师,可以点击链接了解。
参考文档
深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客
智能合约语言 Solidity 教程系列5 - 数组介绍的更多相关文章
- 智能合约语言 Solidity 教程系列1 - 类型介绍
现在的Solidity中文文档,要么翻译的太烂,要么太旧,决定重新翻译下.尤其点名批评极客学院名为<Solidity官方文档中文版>的翻译,机器翻译的都比它好,大家还是别看了. 写在前面 ...
- 智能合约语言 Solidity 教程系列4 - 数据存储位置分析
写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 这部分的内容官方英文文档讲的不是很透,因此我在参考Soli ...
- 智能合约语言 Solidity 教程系列6 - 结构体与映射
写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本系列文章一部分是参考Solidity官方文档(当前最新版 ...
- 智能合约语言 Solidity 教程系列9 - 错误处理
这是Solidity教程系列文章第9篇介绍Solidity 错误处理. Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文 ...
- 智能合约语言Solidity教程系列2 - 地址类型介绍
智能合约语言Solidity教程系列第二篇 - Solidity地址类型介绍. 写在前面 Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你 ...
- 智能合约语言 Solidity 教程系列3 - 函数类型
Solidity 教程系列第三篇 - Solidity 函数类型介绍. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以 ...
- 智能合约语言 Solidity 教程系列8 - Solidity API
这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应 ...
- 智能合约语言 Solidity 教程系列10 - 完全理解函数修改器
这是Solidity教程系列文章第10篇,带大家完全理解Solidity的函数修改器. Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编 ...
- 智能合约语言 Solidity 教程系列7 - 以太单位及时间单位
这是Solidity教程系列文章第7篇介绍以太单位及时间单位,系列带你全面深入理解Solidity语言. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所 ...
随机推荐
- ECMAScript 6 第一天 let和const命令
ES6新增声明变量的方法let命令,const命令. (ES5只有两种声明变量的方法:var 命令和 function 命令.) let命令,用来声明变量. 与var声明变量不同于: 1. let声 ...
- Asp.Net MVC 捆绑(Bundle)
Asp.Net MVC 捆绑(Bundle) 大多数浏览器会对同一域名的请求限制请求数量,一般是在8个以内.每次最多可以同时请求8个,要是资源多于8个,那么剩下的就要排队等待请求了.所以为了提高首次加 ...
- HTML页面加载异常,按F12调试后居然又好了的解决办法!
原因: 你的代码中获取数据那一段应该是有console控制台调用的代码,一般应该是console.log之类的,就是因为这句话在没开F12的时候,console是个undefined的东西就卡在那啦. ...
- 多服务器操作利器 - Polysh
多台服务器下的痛苦人生 分布式架构下的系统,可以说每个服务都是分别部署在多台服务器上的,有的甚至还需要多机房,在这种架构下可以说可以很好的做到了易扩展.容灾等功能.推荐的服务部署为一服务多机器.一机器 ...
- Qt---Xml文件解析
本文我们通过一个读取Xml文件的小例子来学习QXmlStreamReader. Xml 简介 Xml的全称是可扩展标记语言(EXtensible Markup Language),同HTML一样是一种 ...
- 01---Spring框架
Spring框架简介及官方压缩包目录介绍 工厂模式 Spring环境搭建 IoC详解 Spring创建Bean的三种方式(包含两种工厂方式) scope属性讲解 DI详解 Spring中几种注入方式 ...
- 有关nginx的配置文件 之server
下面是vhost中的其中一个xxxx.conf文件 . [Shell] 纯文本查看 复制代码 ? 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 ...
- MySQL 性能优化的最佳20多条经验分享(三)(转)
16. 垂直分割 "垂直分割"是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的.(以前,在银行做过项目,见过一张表有100多个字段, ...
- 【垃圾回收】Java内存回收实践经验 防止内存报警
jdk6和7服务器端(-server) 默认的新生代的垃圾回收器为:PS Scavenge,老年代默认的垃圾回收器为:PS MarkSweep 目前项目使用了jdk7,tomcat7,经常出现内存堆使 ...
- 关于websorm卡顿的问题
要是电脑不卡的话,使用webstorm真可谓是一种享受,但是随着项目的开展,文件逐渐增大,webstorm自然也会出现卡顿(毕竟缺点就是吃内存),这个时候我们可以增加Xms设置 Start1: 1 找 ...