Solidity 0.5.8官方文档

智能合约简介
实例 - 简单存储合约 实例 - 简单子货币合约 区块链基础知识
以太坊虚拟机简介
EVM - 账户 EVM - 交易 EVM - Gas EVM - 内存/存储/栈 EVM - 指令集 EVM - 消息调用 EVM - 委托调用/调用代码/库 EVM - 日志 EVM - 创建其他合约 EVM - 合约停用与自毁
安装Solidity编译器
Solidity编译器版本概述 使用在线Solidity IDE - Remix 使用npm安装Solidity编译器 使用Solidity编译器Docker镜像 安装预构建Solidity编译器 使用源代码构建Solidity编译器
利用实例学习Solidity
实例 - 投票合约 实例 - 盲拍合约 实例 - 安全远程购买合约 实例 - 微支付通道 实例 - 模块化合约
Solidity源文件布局
Pragma - Solidity编译控制指令 导入其他Solidity文件 在Solidity中使用注释
Solidity智能合约的结构
合约 - 状态变量 合约 - 函数 合约 - 函数修饰符 合约 - 事件 合约 - 结构类型 合约 - 枚举类型
Solidity值数据类型
布尔类型 整型 定长浮点数 地址类型 定长字节数组 变长字节数组 地址字面量 数值字面量 字符串字面量 十六进制字面量 枚举类型 数类型
Solidity其他数据类型
引用类型 映射类型 LValue相关的操作符 基本类型之间的转换 字面量类型推断
Solidity内置的计量单位及全局变量
以太币计量单位 时间单位 特殊变量与特殊函数
Solidity表达式和逻辑控制结构
逻辑控制结构 函数调用 使用new创建合约实例 表达式执行顺序 赋值 变量声明与作用域
Solidity智能合约
创建合约 可视性与getter函数 函数修饰符 状态常量 函数参数与返回值 只读函数 纯函数 回退函数 函数重载 使用日志 合约的构造函数 基类构造函数的参数 多重继承与线性化 同名不同类型成员的继承 抽象合约 接口 using for指令
Solidity汇编
内联汇编 - 语法 内联汇编 - 示例 内联汇编 - 操作符 内联汇编 - 字面量 内联汇编 - 函数式风格 内联汇编 - 访问外部变量/函数/库 内联汇编 - 标签 内联汇编 - 声明本地变量 内联汇编 - 赋值 内联汇编 - 条件语句 内联汇编 - 分支语句 内联汇编 - 循环语句 内联汇编 - 函数 使用内联汇编需要避免的错误 Solidity中的惯例 独立汇编的语法
Solidity其他问题
存储中的状态变量布局 内存中的布局 调用数据的布局 变量清理的内部机制 优化器的内部机制 源代码映射 技巧及小窍门
Solidity速查表
操作符优先级 全局变量 函数可见性声明符 修饰符 保留关键字 Solidity语法
NatSpec格式
NatSpec文档示例 使用NatSpec标签 NatSpec文档输出
Solidity安全陷阱
安全陷阱 - 私有信息与随机性 安全陷阱 - 重入问题 安全陷阱 - Gas限量与循环 安全陷阱 - 以太币的发送与接收 安全陷阱 - 调用栈的深度 安全陷阱 - 谨慎使用tx.origin 安全陷阱 - 2的补数/下界溢出/上界溢出 安全相关的小细节
Solidity安全推荐做法
安全推荐 - 认真对待警告信息 安全推荐 - 限定以太币的数量 安全推荐 - 保持合约的简洁与模块化 安全推荐 - 使用检查/生效/交互模式 安全推荐 - 引入故障安全运行模式 安全推荐 - 提请他人审核代码
Solidity安全的正式验证
安全验证 - 抽象与误报 安全验证 - 引用类型与别名
Solidity资源
常规资源 支持Solidity集成的在线服务 Solidity工具 第三方Solidity解析器和语法器
使用Solidity编译器
使用命令行编译器 设置目标EVM版本 编译器输入/输出JSON格式说明
Solidity合约元数据
在合约字节码中嵌入元数据 使用元数据自动生成接口及NatSpec文档 使用元数据进行源代码验证
Solidity合约ABI规范
ABI - 基本设计 ABI - 函数选择符 ABI - 参数编码 ABI - 数据类型 ABI - 编码设计条件 ABI - 编码的形式化约定 ABI - 函数选择符与参数编码 ABI - 示例 ABI - 使用动态类型 ABI - JSON格式 ABI - 严格编码格式 ABI - 非标压缩格式 ABI - 有索引事件参数的编码
Yul规范
Yul - 语法的局限性 Yul - 作用域规则 Yul - 形式化定义 Yul - 类型转换函数 Yul - 底层函数 Yul - 后端 Yul - 对象规范
Solidity风格指南
风格指南简介 代码布局指南 代码布局的顺序 命名惯例 NatSpec风格
Solidity常见模式
模式 - 从合约提款 模式 - 访问限制 模式 - 状态机
在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器

基本类型之间的转换

隐式转换

如果一个运算符用在两个不同类型的变量之间,那么编译器将隐式地将其中一个类型转换为另一个类型(不同类型之间的赋值也是一样)。 一般来说,只要值类型之间的转换在语义上行得通,而且转换的过程中没有信息丢失,那么隐式转换基本都是可以实现的: uint8 可以转换成 uint16,int128 转换成 int256,但 int8 不能转换成 uint256 (因为 uint256 不能涵盖某些值,例如,-1)。 更进一步来说,无符号整型可以转换成跟它大小相等或更大的字节类型,但反之不能。 任何可以转换成 uint160 的类型都可以转换成 address 类型。

显式转换

如果某些情况下编译器不支持隐式转换,但是你很清楚你要做什么,这种情况可以考虑显式转换。 注意这可能会发生一些无法预料的后果,因此一定要进行测试,确保结果是你想要的! 下面的示例是将一个 int8 类型的负数转换成 uint:

int8 y = -3;
uint x = uint(y);

这段代码的最后,x 的值将是 0xfffff..fd (64 个 16 进制字符),因为这是 -3 的 256 位补码形式。

如果一个类型显式转换成更小的类型,相应的高位将被舍弃

uint32 a = 0x12345678;
uint16 b = uint16(a); // 此时 b 的值是 0x5678