玩以太坊链上项目的必备技能(类型-值类型-Solidity之旅二)
admin
2024-03-23 06:51:00
0

Solidity 在编译事需指定变量(状态变量和局部变量)。

虽然 Solidity 受到了 c++、python以及 javascript 的影响,但 undefinednull是不存在的,当然咯,每个新声明的变量总是有默认值的,显然这默认值是跟其声明的类型相关的。

而 Solidity 将类型统归纳为值类型引用类型映射类型。本文将先从值类型讲起。

值类型,顾名思义便是按值进行赋值变量或传递给函数,它们总是会将值拷贝(相对于指针传递,也可以说是引用传递)。

以下这些类型在 Solidity 中都属于 值类型:

  • 布尔类型(bool):字面常量值 truefalse
  • 整型(int/uint):分为有符号整型int和无符号整形uint,这一点倒是和 c++、golang很相像。不管是无符号还有符号整数,它们都是以 8 位递增到 256 位,而intuint分别是int256uint256的别名
  • 定长浮点型:(fixed/ufixed):目前 Solidity 还没完成地支持它,也就是可以在文件中声明这种类型,但却不能赋值给这种类型,同样也不能赋值给其他变量的。ufixedMxNfixedMxN 中,M 表示该类型占用的位数,N 表示可用的小数位数。M是从 8 位 到 256位 ,N则可以是从 0 到 80 之间的任意数。 ufixedfixed 分别是 ufixed128x19fixed128x19 的别名。
  • 地址类型(address):这是 Solidity 特有的类型,存储 20 字节的值(以太坊地址大小)。不过,还有表示可支付的地址类型address payable ,它与address类型相同,不过它有成员函数 transfersend ,以便它可以方便进行以太币转账以及查询。
  • 合约类型(constract):也就是每定义一个constract,便是一个合约类型。
  • 定长字节数组(bytes):bytes1bytes2bytes3...bytes32
  • 有理数和整数字面常量:整数字面常量由范围在 0-9 的一串数字组成,表现成十进制。 例如, 69 表示数字 69。 Solidity 中是没有八进制的,因此前置 0 是无效的。
  • 字符串字面常量及类型(string):字符串字面常量是指由双引号或单引号引起来的字符串( "foo" 或者 'bar'
  • Unicode 字面常量:常规字符串文字只能包含ASCII,而Unicode文字(以关键字unicode为前缀)可以包含任何有效的UTF-8序列。 它们还支持与转义序列完全相同的字符作为常规字符串文字。
  • 十六进制字面常量:十六进制字面常量以关键字 hex 打头,后面紧跟着用单引号或双引号引起来的字符串(例如,hex"001122FF" )。 字符串的内容必须是一个十六进制的字符串,它们的值将使用二进制表示。
  • 枚举类型:枚举是在Solidity中创建用户定义类型的一种方法。 它们是显示所有整型相互转换,但不允许隐式转换。 从整型显式转换枚举,会在运行时检查整数时候在枚举范围内,否则会导致异常( Panic异常])。 枚举需要至少一个成员,默认值是第一个成员,枚举不能多于 256 个成员。
  • 用户定义的值类型:一个用户定义的值类型允许在一个基本的值类型上创建一个零成本的抽象。 这类似于一个别名,但有更严格的类型要求。
  • 函数类型:函数类型是一种表示函数的类型。可以将一个函数赋值给另一个函数类型的变量,也可以将一个函数作为参数进行传递,还能在函数调用中返回函数类型变量。 函数类型有两类: - 内部(internal) 函数类型 - 外部(external) 函数类型

布尔类型(bool)

它是一种非真即假二选一值类型,其取值为truefase

// 布尔运算bool public flag1 = !flag; //取非bool public flag2 = flag && flag1; //与bool public flag3 = flag || flag1; //或bool public flag4 = flag == flag1; //相等bool public flag5 = flag != flag1; //不相等

整数

 // 整型int public num = -7; // 整数,包括负数uint public unum = 7; // 正整数uint256 public big_num = 20221206; // 256位正整数

地址类型

这是一个 Solidity 特有的类型,用于存储合约地址,而地址又可细分为普通地址可支付地址两类。

这种区别背后的思想是 address payable 可以向其发送以太币,而不能先一个普通的 address 发送以太币,例如,它可能是一个智能合约地址,并且不支持接收以太币。

允许从 address payableaddress 的隐式转换,而从 addressaddress payable 必须显示的转换, 通过 payable(

) 进行转换。

 // 地址address public address1 = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;address payable public address2 = payable(address1); // payable address,可以转账、查余额// 地址类型的成员uint256 public balance = address1.balance; // balance of address

定常字节数组

你可能也猜到了,没错,既然有定长字节数组,那么便会有不定长字节数组咯!是的,其实字节数组(bytes)分为定长字节数组不定长字节数组两类,而不定长字节数组属于引用类型,所以放在后面讲。且定常字节数组存放数据,消耗燃料(gas)比较少。

  // 固定长度的字节数组bytes32 public webSite = "qiucode.cn"; bytes1 public myByte = webSite[0]; 

枚举(enum)

枚举是在Solidity中创建用户定义类型的一种方法。 它们是显示所有整型相互转换,但不允许隐式转换。 从整型显式转换枚举,会在运行时检查整数时候在枚举范围内,否则会导致异常( Panic异常 )。 枚举需要至少一个成员,默认值是第一个成员,枚举不能多于 256 个成员。

enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
// 创建enum变量 actionActionChoices action = ActionChoices.GoLeft;

用户定义的值类型

一个用户定义的值类型允许在一个基本的值类型上创建一个零成本的抽象。 这类似于一个别名,但有更严格的类型要求。

用户定义值类型使用 type C is V 来定义,其中 C 是新引入的类型的名称, V 必须是内置的值类型(”底层类型”)。 函数 C.wrap 被用来从底层类型转换到自定义类型。同样地,函数函数 C.unwrap 用于从自定义类型转换到底层类型。

类型 C 没有任何运算符或绑定成员函数。特别是,即使是操作符 == 也没有定义。也不允许与其他类型进行显式和隐式转换。

自定义类型的值的数据表示则继承自底层类型,并且ABI中也使用底层类型。

函数类型

函数类型是一种表示函数的类型。可以将一个函数赋值给另一个函数类型的变量,也可以将一个函数作为参数进行传递,还能在函数调用中返回函数类型变量。 函数类型有两类: - 内部(internal) 函数类型 - 外部(external) 函数类型

内部函数只能在当前合约内被调用(更具体来说,在当前代码块内,包括内部库函数和继承的函数中),因为它们不能在当前合约上下文的外部被执行。 调用一个内部函数是通过跳转到它的入口标签来实现的,就像在当前合约的内部调用一个函数。

外部函数由一个地址和一个函数签名组成,可以通过外部函数调用传递或者返回。

function () {internal|external|public|private} [pure|view|payable] [returns ()] {}
  1. function:声明函数时的固定用法,想写函数,就要以function关键字开头。
  2. :函数名。
  3. ():圆括号里写函数的参数,也就是要输入到函数的变量类型和名字。
  4. {internal|external|public|private}:函数可见性说明符,一共4种。没标明函数类型的,默认internal
    • public: 内部外部均可见。(也可用于修饰状态变量,public变量会自动生成 getter函数,用于查询数值).
    • private: 只能从本合约内部访问,继承的合约也不能用(也可用于修饰状态变量)。
    • external: 只能从合约外部访问(但是可以用this.f()来调用,f是函数名)
    • internal: 只能从合约内部访问,继承的合约可以用(也可用于修饰状态变量)。
  5. [pure|view|payable]:决定函数权限/功能的关键字。payable(可支付的)很好理解,带着它的函数,运行的时候可以给合约转入ETH。constant pure 不能读取也不能写入存储在链上的状态变量。view能读取但也不能写入状态变量。
  6. [returns ()]:函数返回的变量类型和名称。

与参数类型相反,返回类型不能为空 —— 如果函数类型不需要返回,则需要删除整个 returns () 部分。

函数类型默认是内部函数,因此不需要声明 internal 关键字。

请注意,这仅适用于函数类型,合约中定义的函数明确指定可见性,它们没有默认值。

类型转换:

函数类型 A 可以隐式转换为函数类型 B 当且仅当: 它们的参数类型相同,返回类型相同,它们的内部/外部属性是相同的,并且 A 的状态可变性比 B 的状态可变性更具限制性,比如:

  • pure 函数可以转换为 viewnon-payable 函数
  • view 函数可以转换为 non-payable 函数
  • payable 函数可以转换为 non-payable 函数

关于 payablenon-payable 的规则可能有点令人困惑,但实质上,如果一个函数是 payable ,这意味着它 也接受零以太的支付,因此它也是 non-payable 。 另一方面,non-payable 函数将拒绝发送给它的 以太币Ether , 所以 non-payable 函数不能转换为 payable 函数。

如果当函数类型的变量还没有初始化时就调用它的话会引发一个 Panic 异常。 如果在一个函数被 delete 之后调用它也会发生相同的情况。

如果外部函数类型在 Solidity 的上下文环境以外的地方使用,它们会被视为 function 类型。 该类型将函数地址紧跟其函数标识一起编码为一个 bytes24 类型。。

请注意,当前合约的 public 函数既可以被当作内部函数也可以被当作外部函数使用。 如果想将一个函数当作内部函数使用,就用 f 调用,如果想将其当作外部函数,使用 this.f

一个内部函数可以被分配给一个内部函数类型的变量,无论定义在哪里,包括合约和库的私有、内部和public函数,以及自由函数。 另一方面,外部函数类型只与public和外部合约函数兼容。库是不可以的,因为库使用 delegatecall,并且 [他们的函数选择器有不同的 ABI 转换 。 接口中声明的函数没有定义,所以指向它们也没有意义。

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...