2 引用类型

不定长字节数组(bytes)

-动态字节数组

-引用类型(表明可以使用 storage 来修饰,进行引用传递,指针的效果) -支持 下标索引 -支持 length 、 push 方法(push会帮助分配空间的) -可以修改 -以十六进制格式赋值: 'h' -> 0x68 -> 104 -格外注意:对于bytes,如果不使用下标访问,那么可以不用先申请空间, 直接赋值即可,或者 直接push

代码:

pragma solidity ^0.4.24 ;

contract Test{
//动态字节数组,使用new关键字,分配空间
bytes public name=new bytes(32);
bytes public name1;
function setLength(uint _length)public {
  name.length=_length;
}

function getLength(bytes _name)public pure returns(uint){
  return _name.length;
}
  function setName(bytes _name)public {
      name=_name;
     
  }
  function changeName(bytes1 _name)public{
      name[0]=_name;
  }
    /*
  function changeName1(bytes1 _name)public{
      //为未分配空间,访问下表下标错误
      name1[0]=_name;
  }
  */
function pushTest()public{
  name1.push("a");
}
function setInside()public{
  name="hello";
  name1="hello world";
}

字符串(string)

-动态尺寸的UTF-8编码字符串,是特殊的可变字节数组 -引用类型 -不支持下标索引 -不支持length、push方法 -可以修改(需通过bytes转换)

-使用下标索引的话,转成bytes类型

代码:

pragma solidity ^0.4.24;
contract String{
  //引⽤用类型;不支持下标索引;不支持length、push⽅方法;可以修改(需通过bytes转换)
  //下表x索引,length都转换成不用bytes来操作
  string public name="steven";
  function nameBytes()constant returns(bytes){
      return bytes(name);
  }
  function nameLength()constant returns(uint){
      //return name.lengh; //z不支持直接使用
      return bytes(name).length;
  }
  function changeName()public{
  name="mark";
// name[1}="l";不支持直接索引
bytes(name)[0]="l";

}
  function changeLength()public{
      bytes(name).length=10;
  }
   

数据位置(Data location)

复杂类型,不同于之前 值类型 ,占的空间更大,超过256字节,因为拷贝它们占用更多的空间,如数组(arrays) 和 数据结构(struct) ,他们在Solidity中有一个额外的属性,即数据的存储位置: memory 和 storage 。

​ - 内存(memory)

数据不是永久存在的,存放在内存中,越过作用域后无法访问,等待被回收; 被memory修饰的变量是直接拷贝,即与上述的值类型传递方式相同。

-存储 (storage)

数据永久保存在。 被storage修饰的变量是引用传递,相当于只传地址,新旧两个变量指向同一片内存空间,效率较高,两个变量有关联,修改一个,另外一个同样被修改; 只有引用类型的变量才可以显示的声明为 storage 。

  • 状态变量量

状态变量总是stroage类型的,无法更改;

  • 局部变量量

默认是storage类型(仅限数据结构或数组,string),但是可以声明为memory类型。

-对于非值的数据类型,比如数组和结构体,赋值的语法比较复杂:

.赋值给一个状态变量总是创建一个完全无关的拷贝

.赋值给一个局部变量,仅对基本类型,如那些32字节以内的(静态类型(static types)),创建一份完全无关的拷贝;

.如果是数据结构或数组,(包括bytes和string)类型,由状态变量赋值为一个局部变量,局部变量只是持有原始状态变量的一个引用。对于这个局部变量再次赋值,并不会修改这个状态变量,只是修改了引用(局部变量指向了别人);但是修改这个本地引用变量(局部变量)的成员值,会改变状态变量的值(修改了所引用的状态变量值)localTest()的测试

代码:

pragma solidity ^0.4.24;

contract test2{
  //memory:存放在内存中,不是永久存在,超越于作用域后,等待被回收;志值传递
  //storage:数据永久保存,引用传递传递,c效率高
  //状态变量变量总是storage类型;局部变量是storage(仅限数据结构或数组,string),但是可以memory
string public name= 'lily';
uint256 public num = 10;

function call1() public {
  setName1(name);
}
//对于引用数据类型,作为函数参数时 默认是memory类型(值传递)
function setName1(string src) private {
//function setName1(string memory src) private {
  num = 100; //num变为100
  bytes(src)[0] = "L";//name还是小写
}
function call2() public {
  setName2(name);
}
   
//如果想引用传递,需要显示指明storage
function setName2(string storage src) private {
      num = 1000;//num为1000
      bytes(src)[0] = "L";//name变成大写
  }
   
//如果局部变量是string,数组,结构体类型数据,默认是storage类型    
function localTest () public {
  string memory tmp = name;
  bytes(tmp)[0] = "L";//name变大写
}

转换(byte1/bytes/string)

pragma solidity ^0.4.24;
contract Transformation{
  //(byte1/bytes/string)相互转换
   
    bytes10 b10 = 0x68656c6c6f776f726c64;     //helloworld
  //bytes bs10 = b10; //⽆无法直接转换
   
 
  bytes public bs10 = new bytes(b10.length);
   
  //1. 固定字节数组转动态字节数组;需要逐一赋值
  function fixedBytesToBytes() public{
      for (uint i = 0; i< b10.length; i++){
          bs10[i] = b10[i];
      }
  }
  //2.string转动态字节数组
  string greeting = "helloworld";
  bytes public b1;
  function StringToBytes() public {
      b1 = bytes(greeting);
  }
  //3. 动态字节数组转string
  string public str3;
  function BytesToString() public {
      fixedBytesToBytes();
      str3 = string(bs10);
  }
    function FiexBytesToString(){
    //固定字节数组和string无法转换
      //string tmp = string(b10);
  }
   
}

数组

-内置数组:string(不定长)、bytes(不定长)、byte1,byte2...(定长);

-自定义数组:

类型T,长度K的数组定义为T[K],例如:uint [5] numbers, byte [10] names; 内容可变; 长度不可变,不支持push; 支持length方法。

-不定长数组:

定义格式为T [ ],例例如:string[ ] names, byte[ ] citys; 内容可以修改; 可以改变长度(仅限storage类型) 支持 length 、 push 方法; memory类型的不定长数组不支持修改长度;

pragma solidity ^0.4.24;
contract C {
  /*
  定长数组
  */
    uint[10] value = [1,2,3,4,5];
    uint public sum;
   
  function getSum()public returns(uint ){
      sum=0;
      for (uint i = 0; i < value.length; i++){
          sum += value[i];
           
      }
      return sum ;
  }
  function changeValue(){
      value[0] = 2; //内容可修改
      //value.length = 100; //报错,长度不可修改
  }    
   
  //test2:
  //helloworld : 0x68656c6c6f776f726c64
  bytes10 helloworldFixed = 0x68656c6c6f776f726c64;
  byte [10] helloworldDynamic = [byte(0x68), 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64];
  bytes helloworld;
   
  function changeByte() public {
      //helloworldFixed[0] = 0x69; //error
      helloworldDynamic[0] = 0x69; //ok
  }
   
function getString () public constant returns (string) {
  for (var i = 0; i < helloworldDynamic.length; i++) {
    helloworld.push(helloworldDynamic[i]);//不定长字节数组,没有开辟空间,可以直接赋值或者push
      }
       
      return string(helloworld);
  }

结构体

pragma solidity ^0.4.24;
contract StructType{
    //定义结构之后无分号,与枚举⼀致
  struct Student{
      string name;
      uint age;
      uint score;
      string sex;
  }
  Student []public Students;//定义结构体数组
  //看两种赋值方式
  Student public stu1=Student("steven",18,99,"m");
  Student public stu2=Student({name:"mark",age:19,score:90,sex:"w"});
  function assign()public{
      Students.push(stu1);
      Students.push(stu2);
      stu1.name="lily";
   
}
}

字典/映射/哈希(mapping)

-键key的类型允许除映射外的所有类型,如数组,合约,枚举,结构体,值的类型无限制; -无法判断一个mapping中是否包含某个key,因为它认为每一个都存在,不存在的返回0或false; -映射可以被视作为一个哈希表,在映射表中,不存储键的数据,仅存储它的 keccak256 哈希值,用来查找值时使用; -映射类型,仅能用来定义状态变量,或者是在内部函数中作为storage类型的引用。 -不支持length -key不支持string 类型​

pragma solidity ^0.4.24;

contract test{
  //id->name
  mapping(uint=>string)id_name;
  constructor ()public{
      //构造函数
      id_name[0x01]="steven";
      id_name[0x02]="lily";
      id_name[0x03]="mark";
}
function getNameById(uint id)public view returns(string){
  string memory name=id_name[id];
  return name;
}
}

引用类型之间的比较

12-19 10:39
查看更多