https://blog.csdn.net/weixin_45067603/article/details/105726491
1.### 整型
int
/ uint
:分别表示有符号和无符号的不同位数的整型变量。 支持关键字 uint8
到 uint256
(无符号,从 8 位到 256 位)以及 int8
到 int256
,以 8
位为步长递增。 uint
和 int
分别是 uint256
和 int256
的别名。
2.### 定长字节数组
关键字有:bytes1, bytes2, bytes3, …, bytes32。 byte 是 bytes1 的别名。
成员变量:
.length 表示这个字节数组的长度(只读).
变长字节数组
bytes
变长字节数组,参见 数组。它并不是值类型。
string
变长 UTF-8 编码字符串类型,参见 数组。并不是值类型。
字符串 转 动态数组
string str = "mystr";
bytes b = bytes(str);
动态数组 转 字符串
bytes bs = 0x7a4892;
string str = string(b);
定长字节数组之前可以互相转换
bytes1 b1= 0x7a;
bytes2 b2=bytes2(b1);
定长字节数组 转 动态字节数组
固定长度数组:
1.如果不赋值,那么默认所有位均为0
2.支持直接使用.length查看数组长度,但不支持对数组长度做修改
3.不支持通过.push添加数据
contract fixedarrtest{
uint[3] testarr1;//不进行赋值直接声明数组
uint[3] testarr2=[1,2,3];//声明数组并进行赋值
function showarr1() public view returns(uint[3]){
return testarr1; //如果不赋值,那么默认所有位均为0
}
function showarr2() public view returns(uint[3]){
return testarr2;
}
function initarr() public{
testarr1[0]=12;//进行赋值操作
}
function lengthtest() public view returns(uint){
return testarr1.length;//solidity支持直接查看数组长度
}
可变数组:
1.支持直接使用.length查看数组长度,也支持对数组长度做修改。
将数组长度缩小则会从前往后保留
将数组长度增长则后面原本没有值的位会被默认置0
2.支持直接通过.push方法在末尾添加数值
contract dynamicarrtest{
uint[] testarr=[1,2,3,4,5];
function showarr() public view returns (uint[]){
return testarr;
}
function changearr() public{
//for(uint i=0;i<5;i++){
testarr[0] = 2;//如果不使0位有值,那么该函数无用
//}
}
function lengthtest() public view returns(uint){
return testarr.length;
}
function changelengthtest1() public{
testarr.length=1;
}
function changelengthtest2() public{
testarr.length=10;//变长之后后面默认置0
}
function pushtest() public{
testarr.push(6);//可变数组支持此操作
}
}
二维数组
1.初始化时,uint[ i ] [ j ]表示有j个元素,每个元素包含i个值(和其他许多语言不同)
2.二维数组可以直接获取长度,既可以获得所有元素个数,也可以获得单独元素有多少值
3.对二维数组进行增删改等操作时时是与初始化时反过来的,即uint[ i ] [ j ]表示第i个元素的第j个值(和其他许多语言一样)
4.不支持push方法,也不支持对长度进行修改
pragma solidity ^0.4.0;
contract TwoArray{
// 定义二维数组 3行2列: 3个元素 每个元素里有2个值
uint[2][3] grade = [[1,2],[3,4],[6,5]];
//获取行数
function getOneLength() returns(uint){
return grade.length; // 3
}
// 获取列数
function getTwoLength() returns(uint){
return grade[0].length; //2
}
// 获取值
function getData() returns(uint[2][3]){
return grade;
}
//求和
function getSum() returns(uint){
uint sum = 0;
for(uint i = 0; i < grade.length; i++){
for(uint j = 0; j < grade[i].length; j++){
sum += grade[i][j];
}
}
return sum;
}
// 改变数组的值 : 改变第一个元素的第二个值
function changeData() {
grade[1][2] = 100;
}
}
地址类型成员变量
1.以太坊中的地址的长度为20字节,一字节等于8位,一共160位,所以address其实亦可以用uint160来声明。比如:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4转uint160就是520786028573371803640530888255888666801131675076(16进制转10进制)
2.地址之间支持大小比较
1.可以通过地址.balance获取某个地址的余额
2.this指的是当前合约的地址,如此处就是paytest合约的地址
3.转账可以通过remix图形界面来进行转账数目的改变
4.对其他账户的转账需要使用账户名称.transfer(msg.value)或者账户名称.transfer(数量 单位,如1 ether)如果在输入value的同时又写的是数量 单位,那么多余的value就自动转账到合约地址里去
5.如果对当前合约使用transfer转账this.transfer(msg.value)则必须需要一个回滚函数。
6…如果函数含有payable而函数里面没有要求给某个账户转账的话,则会默认转账到合约当中
7.send和transfer的区别是,前者是底层函数,返回bool值;后者会直接在调用时报错。具体体现在如果转账金额为0是,send正常运行但是返回false 现在尝试了之后发现即使转账金额0,两者均都不报错,返回的为true,见测试5
查看所有的成员,可参考 地址成员。
-
balance
和transfer
pragma solidity ^0.4.0;
contract addressTest{
address public account = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
// address 转 uint160 其实就是 16进制 转 10进制
function addressToInt16() view returns(uint160){
return uint160(account);
}
// 加上payable 就默认是给 当前合约转账 msg.value的数额
function toContract() payable {
}
// 获取当前合约地址, 合约也是可以转账的
function getThis() view returns(address){
return this;
}
// 获取合约余额
function getContractBalance() view returns(uint){
return this.balance;
}
// 获取指定地址的余额, address类型默认属性balance
function getAccountBalance(address acc) view returns(uint){
return acc.balance;
}
// 给acc 转账 msg.value; msg.value是全局变量,转账的数额
function transfer(address acc) payable {
acc.transfer(msg.value);
}
// 使用send 进行转账
function send(address acc) payable returns(bool){
return acc 使用send 进行转账(msg.value);
}
}
3.全局变量
2.函数类型:
函数类型表示成如下的形式
function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]
函数类型有两类:
内部(internal) 函数类型
外部(external) 函数类型
public(或 external)函数都有下面的成员:
-
.address
返回函数的合约地址。 -
.selector
返回 ABI 函数选择器
映射类型在声明时的形式为 mapping(_KeyType => _ValueType)
。 其中 _KeyType
可以是任何基本类型,即可以是任何的内建类型加上bytes
和 string
。 而用户定义的类型或复杂的类型如:合约类型、枚举、映射、结构体、即除 bytes
和 string
之外的数组类型 是不可以作为 _KeyType
的类型的。
_ValueType
可以是包括映射类型在内的任何类型
在映射中,实际上并不存储 key,而是存储它的 keccak256 哈希值,从而便于查询实际的值。
映射只能是 存储 的数据位置,因此只允许作为状态变量 或 作为函数内的 存储 引用 或 作为库函数的参数。 它们不能用合约公有函数的参数或返回值
可以将映射声明为 public
,然后来让 Solidity 创建一个 getter 函数。 _KeyType
将成为 getter 的必须参数,并且 getter 会返回 _ValueType
。
pragma solidity ^0.4.0;
contract mappingUse{
// 定义mapping
mapping(address => string) myName;
// mapping 赋值
function setName(string name) {
myName[msg.sender] = name;
}
// mapping取值
function getName(address acc) view returns(string) {
return myName[acc];
}
}
引用类型可以通过多个不同的名称修改它的值,而值类型的变量,每次都有独立的副本。因此,必须比值类型更谨慎地处理引用类型。 目前,引用类型包括结构,数组和映射,如果使用引用类型,则必须明确指明数据存储哪种类型的位置(空间)里:
内存memory 即数据在内存中,因此数据仅在其生命周期内(函数调用期间)有效。不能用于外部调用。
存储storage 状态变量保存的位置,只要合约存在就一直存储.
调用数据calldata 用来保存函数参数的特殊数据位置,是一个只读位置。
更改数据位置或类型转换将始终产生自动进行一份拷贝,而在同一数据位置内(对于 存储 来说)的复制仅在某些情况下进行拷贝。
在 存储 和 内存 之间两两赋值(或者从 调用数据 赋值 ),都会创建一份独立的拷贝。
从 内存 到 内存 的赋值只创建引用, 这意味着更改内存变量,其他引用相同数据的所有其他内存变量的值也会跟着改变。
从 存储 到本地存储变量的赋值也只分配一个引用。
其他的向 存储 的赋值,总是进行拷贝。