锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

【第三章】初识别solidity值类型

时间:2023-11-13 18:37:00 二极管模块mee75

以下类型也称为值类型,因为这些类型的变量总是按值传递,即当它们用作函数参数或赋值时,它们总是被复制。

布尔值

bool: 常数是可能的值true和false。

运营商:

  • !(逻辑否定)
  • &&(逻辑连接,和)
  • ||(逻辑析取,或)
  • ==(平等)
  • !=(不等式)

运营商||并&&应用常见的短路规则。这意味着在表达式中,即使有副作用,也不会计算计算结果。f(x)||g(y)f(x)trueg(y)

整数

int/uint:各种尺寸都有符号和无符号整数。uint8touint256(8无符号 8 到 256 位)和int8toint256。uint和分别是和int的别名。uint256int256

运营商:

  • 比较:<=,<,==,!=,>=,>(计算为bool)
  • 位运算符:&,|,^(按位异或),~(按位否定)
  • 移位运算符:(<<左移)、>>(右移)
  • 算术运算符: ,-, 一元-(仅适用于符号整数),*,/,%(模),**(幂)

对于整数类型X,您可以使用type(X).min和type(X).max访问该类型可以表示的最小值和最大值。

警告

Solidity 在一定范围内定范围内。例如,使用uint这0取决于32。对这些类型执行算术运算有两种模式:“包装”或“未检查”模式和“已检查”模式。在默认情况下,算术总是检查的,这意味着如果操作结果超出了类型值范围,则通过失败的断言恢复。您可以使用 切换到未选择模式。有关更多细节unchecked在部分中找到。2**32-1unchecked{...}

比较

比较值是通过比较整数值获得的值。

位操作

数字二进制补码表示执行位运算。这意味着,例如.~int256(0)==int256(-1)

转移

移位操作结果为左操作数的类型,截断结果为匹配类型。右操作数必须为无符号类型,并尝试根据符号类型进行编译错误。

乘以可以通过以下方式使用 2 模拟模拟移位。请注意,左操作数的截断总是在最后执行,但没有明确提及。

  • x<等同于数学表达式。x*2**y

  • x>>y等价于数学表达式,向负无穷舍入。x/2**y

警告

在这个版本之前,负数0.5.0右移相当于零舍入的数学表达式,即使用向上舍入(向零)而不是向下舍入(向负无限大)进行右移。x>>yxx/2**y

笔记

移位操作永远不会像算术操作那样进行溢出检查。相反,结果总是被切断。

加法、减法和乘法

加法、减法和乘法有两种不同的模式:

在默认情况下,检查所有算术是否不足或溢出,但可以使用unchecked block该功能被禁用,导致算术包装。在这一部分可以找到更多的细节。

该表达式-x等价于whereis 类型。它只能用于签名类型。如果是负的,值可以是正的。二进制补码还有另一个警告:(T(0)-x)Tx-xx

如果有,则不适合正值范围。这意味着有效,并在检查模式下使用表达式会导致断言失败。intx=type(int).min;-xunchecked{assert(-x==x);}-x

分配

由于计算结果的类型总是操作数之一,整数除法总是产生整数。 Solidity 除法零舍入。这意味着.int256(-5)/int256(2)==int256(-2)

请注意,相比之下,文生任何精度的小值。

笔记

除以零会导致Panic 错误。无法通过 禁止此检查。unchecked{...}

笔记

表达式是除法造成溢出的唯一情况。在检查算术模式下,这将导致断言失败,而在包装模式下,该值将是.type(int).min/(-1)type(int).min

模数

操作数产生操作数除以操作数后的余数,其中和。这意味着模具操作的结果与左操作数(或零)相同,并设置负数:a%nranq=int(a/n)r=a-(n*q)a%n==-(-a%n)a

  • int256(5)%int256(2)==int256(1)

  • int256(5)%int256(-2)==int256(1)

  • int256(-5)%int256(2)==int256(-1)

  • int256(-5)%int256(-2)==int256(-1)

定点数

Solidity 固定点数还没有完全支持。它们可以声明,但不能分配给或来自。

fixed/ufixed:有符号和无符号定点数的各种尺寸。关键字ufixedMxNandfixedMxN,M表示类型占用的位数,N有多少个小数点可用。M必须能被 8 从 8 位变为 256 位。N必须介于 0 和 80 之间,包括 0 和 80。ufixed和分别是和fixed的别名。ufixed128x18fixed128x18

地址

地址有两种类型,基本相同:

  • address:保存一个 20 字节值(以太坊地址大小)。
  • addresspayable:与 相同address,但具有附加成员transfer和send。

这种差异背后的想法是,你可以 Ether 你不应该把它发送到地址 Ether 发送到 plain,例如,因为它可能被接受吗? Ether 构建的智能合同。addresspayableaddress

类型转换:

允许从to而从to的转换必须通过.addresspayableaddressaddressaddresspayablepayable(

)

address允许对uint160、整数文字bytes20合同类型的显式转换。

只有 typeaddress和 contract-type 表达式可以通过显式转换为类型。对于合同类型,这种转换只有在合同能够接收以太币时才允许,即合同要么具有接收或处理退货的功能。请注意,这是有效的,也是本规则的例外。addresspayablepayable(...)payable(0)

合约类型

每个合同都定义了自己的类型。您可以将合同隐式转换为他们继承的合同。合同可以显式转换为address类型。

只有当合同类型具有接收或应付回报功能时,才能显式转换类型。转换仍在使用.如果合同类型没有接收或应付回报功能,则可以使用.您可以在地址类型中找到更多信息。addresspayableaddress(x)addresspayablepayable(adress(x))

 

合约类型的成员是合约的外部函数,包括任何标记为 的状态变量public。

对于合同C,您可以使用它type(C)来访问 有关合同的类型信息。

 

字节数组

 

固定大小的字节数组

值类型bytes1bytes2bytes3, ...bytes32 包含从 1 到最多 32 的字节序列。

运营商:

  • 比较:<=<==!=>=>(计算为bool

  • 位运算符:&|^(按位异或),~(按位否定)

  • 移位运算符:(<<左移)、>>(右移)

  • 索引访问:如果x是 type bytesI,则x[k]for返回第th 字节(只读)。0 <= k < Ik

移位运算符使用无符号整数类型作为右操作数(但返回左操作数的类型),它表示要移位的位数。按有符号类型移位会产生编译错误。

 

地址字面量

 

例如,通过地址校验和测试的十六进制文字 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF属于address类型。长度在 39 到 41 位之间且未通过校验和测试的十六进制文字会产生错误。您可以预先(对于整数类型)或附加(对于 bytesNN 类型)零来消除错误。

笔记

混合大小写地址校验和格式在EIP-55中定义。

 

有理数和整数字面量

 

整数文字由 0-9 范围内的数字序列组成。它们被解释为小数。例如,69表示六十九。Solidity 中不存在八进制文字,前导零无效。

十进制小数文字由.一侧至少有一个数字的 a 组成。示例包括1.和。.11.3

还支持以 的形式的科学记数法2e10,其中尾数可以是小数,但指数必须是整数。字面MeE量等价于。示例包括, , , 。M * 10**E2e10-2e102e-102.5e1

下划线可用于分隔数字文字的数字以提高可读性。例如,十进制123_000、十六进制0x2eff_abde、科学十进制记数法1_2e345_678都是有效的。下划线只允许在两位数之间,并且只允许一个连续的下划线。包含下划线的数字文字没有添加额外的语义含义,下划线被忽略。

数字文字表达式保持任意精度,直到它们被转换为非文字类型(即通过将它们与数字文字表达式(如布尔文字)以外的任何内容一起使用或通过显式转换)。这意味着计算不会溢出,除法不会在数字文字表达式中截断。

例如,虽然中间结果甚至不适合机器字长,但结果为常量(类型为)。此外,结果为整数(尽管在两者之间使用了非整数)。(2**800 + 1) - 2**8001uint8.5 * 84

警告

虽然大多数运算符在应用于文字时都会产生文字表达式,但有些运算符不遵循此模式:

  • 三元运算符 ( ),... ? ... : ...
  • 数组下标 ( [])。

您可能希望表达式或等价于直接使用文字 256,但实际上它们是在类型内计算的并且可能溢出。255 + (true ? 1 : 0)255 + [1, 2, 3][0]uint8

只要操作数是整数,任何可以应用于整数的运算符也可以应用于数字文字表达式。如果两者中的任何一个是小数,则不允许位运算,并且如果指数是小数,则不允许取幂(因为这可能导致非有理数)。

将文字数字作为左(或基)操作数和整数类型作为右(指数)操作数的移位和取幂总是在uint256(对于非负文字)或int256(对于负文字)类型中执行,无论右(指数)操作数。

 

uint128 a = 1;
uint128 b = 2.5 + a + 0.5;
//qq201333403

 

字符串字面量和类型

 

字符串文字用双引号或单引号("foo"or 'bar')编写,它们也可以分成多个连续的部分(相当于),这在处理长字符串时很有帮助。它们并不意味着 C 中的尾随零;代表三个字节,而不是四个。与整数文字一样,它们的类型可能会有所不同,但它们可以隐式转换为, ..., ,如果它们适合,则可以转换为和。"foo" "bar""foobar""foo"bytes1bytes32bytesstring

例如,字符串文字在分配给类型时以其原始字节形式解释。bytes32 samevar = "stringliteral"bytes32

字符串文字只能包含可打印的 ASCII 字符,即 0x20 .. 0x7E 之间的字符。

此外,字符串文字还支持以下转义字符:

  • \(转义一个实际的换行符)
  • \\(反斜杠)
  • \'(单引号)
  • \"(双引号)
  • \n(新队)
  • \r(回车)
  • \t(标签
  • \xNN(十六进制转义,见下文)
  • \uNNNN(unicode转义,见下文)

\xNN采用十六进制值并插入适当的字节,同时\uNNNN采用 Unicode 代码点并插入 UTF-8 序列。

 

在 0.8.0 版本之前,还有三个额外的转义序列\b:\f和\v. 它们通常以其他语言提供,但在实践中很少需要。如果您确实需要它们,它们仍然可以像任何其他 ASCII 字符一样分别通过十六进制转义符插入,\x08即\x0c 和。\x0b

以下示例中的字符串长度为 10 个字节。它以换行字节开头,后跟双引号,单引号和反斜杠字符,然后(不带分隔符)字符序列abcdef。

 

"\n\"\'\\abc\
def"

任何不是换行符的 Unicode 行终止符(即 LF、VF、FF、CR、NEL、LS、PS)都被视为终止字符串文字。换行符仅在字符串文字前面没有 . 时才终止\。

 

Unicode 字面量

 

虽然常规字符串文字只能包含 ASCII,但 Unicode 文字(以关键字为前缀unicode)可以包含任何有效的 UTF-8 序列。它们还支持与常规字符串文字完全相同的转义序列。

 

string memory a = unicode"Hello 😃";

 

十六进制字面量

 

十六进制文字以关键字为前缀,hex并用双引号或单引号 ( hex"001122FF", hex'0011_22_FF') 括起来。它们的内容必须是十六进制数字,可以选择使用单个下划线作为字节边界之间的分隔符。文字的值将是十六进制序列的二进制表示。

由空格分隔的多个十六进制文字连接成一个文字: 相当于hex"00112233" hex"44556677"hex"0011223344556677"

十六进制文字的行为类似于字符串文字,并且具有相同的可转换性限制。

 

枚举

 

枚举是在 Solidity 中创建用户定义类型的一种方式。它们可以显式转换为所有整数类型,但不允许隐式转换。整数的显式转换在运行时检查该值是否在枚举范围内, 否则会导致Panic 错误。枚举至少需要一个成员,声明时它的默认值是第一个成员。枚举不能有超过 256 个成员。

数据表示与 C 中的枚举相同:选项由从 开始的后续无符号整数值表示0。

使用type(NameOfEnum).minandtype(NameOfEnum).max你可以获得给定枚举的最小值和最大值。

// SPDX-License-Identifier: GPL-3.0
//q群54548027
pragma solidity ^0.8.8;

contract test {
    enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
    ActionChoices choice;
    ActionChoices constant defaultChoice = ActionChoices.GoStraight;

    function setGoStraight() public {
        choice = ActionChoices.GoStraight;
    }

    // Since enum types are not part of the ABI, the signature of "getChoice"
    // will automatically be changed to "getChoice() returns (uint8)"
    // for all matters external to Solidity.
    function getChoice() public view returns (ActionChoices) {
        return choice;
    }

    function getDefaultChoice() public pure returns (uint) {
        return uint(defaultChoice);
    }

    function getLargestValue() public pure returns (ActionChoices) {
        return type(ActionChoices).max;
    }

    function getSmallestValue() public pure returns (ActionChoices) {
        return type(ActionChoices).min;
    }
}

 

用户定义的值类型

 

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

用户定义的值类型使用 定义,其中是新引入类型的名称,并且必须是内置值类型(“基础类型”)。该函数 用于从底层类型转换为自定义类型。同样,该函数用于从自定义类型转换为基础类型。type C is VCVC.wrapC.unwrap

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

这种类型的值的数据表示是从底层类型继承的,底层类型也在 ABI 中使用。

以下示例说明了一个自定义类型,该类型UFixed256x18表示具有 18 个小数的小数定点类型和一个用于对该类型进行算术运算的最小库。

// SPDX-License-Identifier: GPL-3.0
//q201333403
pragma solidity ^0.8.8;

// Represent a 18 decimal, 256 bit wide fixed point type using a user defined value type.
type UFixed256x18 is uint256;

/// A minimal library to do fixed point operations on UFixed256x18.
library FixedMath {
    uint constant multiplier = 10**18;

    /// Adds two UFixed256x18 numbers. Reverts on overflow, relying on checked
    /// arithmetic on uint256.
    function add(UFixed256x18 a, UFixed256x18 b) internal pure returns (UFixed256x18) {
        return UFixed256x18.wrap(UFixed256x18.unwrap(a) + UFixed256x18.unwrap(b));
    }
    /// Multiplies UFixed256x18 and uint256. Reverts on overflow, relying on checked
    /// arithmetic on uint256.
    function mul(UFixed256x18 a, uint256 b) internal pure returns (UFixed256x18) {
        return UFixed256x18.wrap(UFixed256x18.unwrap(a) * b);
    }
    /// Take the floor of a UFixed256x18 number.
    /// @return the largest integer that does not exceed `a`.
    function floor(UFixed256x18 a) internal pure returns (uint256) {
        return UFixed256x18.unwrap(a) / multiplier;
    }
    /// Turns a uint256 into a UFixed256x18 of the same value.
    /// Reverts if the integer is too large.
    function toUFixed256x18(uint256 a) internal pure returns (UFixed256x18) {
        return UFixed256x18.wrap(a * multiplier);
    }
}

注意UFixed256x18.wrap和如何FixedMath.toUFixed256x18具有相同的签名但执行两个非常不同的操作:UFixed256x18.wrap函数返回UFixed256x18 与输入具有相同数据表示的 a,而toUFixed256x18返回 UFixed256x18具有相同数值的 a。

 

函数类型

 

函数类型是函数的类型。函数类型的变量可以从函数中赋值,函数类型的函数参数可以用来传递函数到函数调用和从函数调用返回函数。函数类型有两种形式——内部函数和外部函数:

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

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

函数类型表示如下:

function () {internal|external} [pure|view|payable] [returns ()]

与参数类型相比,返回类型不能为空——如果函数类型不应返回任何内容,则 必须省略整个部分。returns ()

默认情况下,函数类型是内部的,因此internal可以省略关键字。请注意,这仅适用于函数类型。必须为合约中定义的函数明确指定可见性,它们没有默认值。

转换:

当且仅当它们的参数类型相同、返回类型相同、内部/外部属性相同并且 的状态可变性 比 的状态可变性更具限制性时,函数类型A才能隐式转换为函数类型。尤其:BAB

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

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

  • payable函数可以转换为non-payable函数

函数类型之间没有其他转换是可能的。

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

如果未初始化函数类型变量,则调用它会导致Panic 错误。如果您在使用后调用函数,也会发生同样的情况delete 。

如果在 Solidity 的上下文之外使用外部函数类型,它们将被视为function类型,它将地址和函数标识符一起编码为一个bytes24类型。

请注意,当前合约的公共功能既可以用作内部功能,也可以用作外部功能。要f用作内部函数,只需使用f,如果要使用其外部形式,请使用this.f

内部类型的函数可以分配给内部函数类型的变量,而不管它是在哪里定义的。这包括合约和库的私有、内部和公共功能以及免费功能。另一方面,外部函数类型仅与公共和外部合约函数兼容。库被排除在外,因为它们需要一个delegatecall并为其选择器使用不同的 ABI 约定。接口中声明的函数没有定义,因此指向它们也没有意义。

 

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章