玩以太坊链上项目的必备技能(类型-值类型-Solidity之旅二)

news/2024/5/19 2:13:04 标签: 区块链, solidity, 值类型, 函数类型, 枚举

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

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

整数

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

地址类型

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

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

允许从 address payableaddress 的隐式转换,而从 addressaddress payable 必须显示的转换, 通过 payable(<address>) 进行转换。

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

定常字节数组

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

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

枚举(enum)

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

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

用户定义的值类型

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

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

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

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

函数类型

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

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

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

function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)] {

}
  1. function:声明函数时的固定用法,想写函数,就要以function关键字开头。
  2. <function name>:函数名。
  3. (<parameter types>):圆括号里写函数的参数,也就是要输入到函数的变量类型和名字。
  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 (<return types>)]:函数返回的变量类型和名称。

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

函数类型默认是内部函数,因此不需要声明 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 转换 。 接口中声明的函数没有定义,所以指向它们也没有意义。


http://www.niftyadmin.cn/n/14828.html

相关文章

GitHub 的 9 种加速方式

1. GitHub 镜像访问 这里提供两个最常用的镜像地址&#xff1a; https://github.com.cnpmjs.org https://hub.fastgit.org 也就是说上面的镜像就是一个克隆版的 GitHub&#xff0c;你可以访问上面的镜像网站&#xff0c;网站的内容跟 GitHub 是完整同步的镜像&#xff0c;然…

年龄到了一定程度才能体会到世界杯的真正意义

前言 聊起来世界杯&#xff0c;想必读者们都有说不完的世界杯话题&#xff0c;四年一届的全球盛会&#xff0c;把全世界的目光都牢牢的拿捏在手里&#xff0c;世界杯不仅仅是关于足球的比赛活动&#xff0c;而且更是团队协作精神、永不言弃等精神的体现和传承。年轻的时候可能是…

基于独立分量分析进行模态分解(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

CUDA入门和网络加速学习(一)

0. 简介 最近作者希望系统性的去学习一下CUDA加速的相关知识&#xff0c;正好看到深蓝学院有这一门课程。所以这里作者以此课程来作为主线来进行记录分享&#xff0c;方便能给CUDA网络加速学习的萌新们去提供一定的帮助。 1. GPU与CPU区别 处理器指标一般主要分为两大类&…

Spring Cloud(十四):微服务灰度发布 --- Discovery

灰度发布微服务全链路灰度全链路灰度设计思路 标签路由节点打标流量染色分布式链路追踪 ThreadLocal流量治理平台 Nacos 配置中心 全链路灰度实现Discovery使用 一、父pom引入Discovery二、Gateway 引入 — 网关 discovery-plugin-strategy-starter-gateway三、微服务 引入 — …

云原生|kubernetes|使用cri-docker部署基于kubeadm-1.25.4的集群

前言&#xff1a; kubernetes的部署从1.24版本开始后&#xff0c;弃用docker-shim&#xff0c;也就是说部署1.24版本后的集群不能使用docker-ce了。 比较清晰的解决方案有两个&#xff0c;一是使用containerd&#xff0c;这个是一个新的支持cri标准的shim&#xff0c;一个是使…

2023年天津美术学院专升本专业课报名缴费时间及考试安排

天津美术学院2023 年高职升本专业考试报名考试公告 一、报名时间 2022 年 12 月 9 日 10:00 至 12 月 12 日 17:00&#xff08;逾期不予补报&#xff0c;考生也不得再修改报名信息&#xff09; 注&#xff1a;每日 23:00 至次日 7:00 是报名系统维护时间&#xff0c;届时报名相…

Linux系统移植五:启动开发板并测试

往期文章 Linux系统移植一&#xff1a;移植U-BOOT 添加自己的板子并编译&#xff08;非petalinux版&#xff09; Linux系统移植二&#xff1a;生成fsbl引导文件并制作BOOT.bin Linux系统移植三&#xff1a;移植Kernel生成zImage和dtb文件 Linux系统移植四&#xff1a;Petalinu…