热点、深度、趋势全掌握,尽在BTC区块圈

【solidity必知】详解 solidity 数据存储的三种方式

在 Solidity 里,数据存储方式主要分为存储(storage)、内存(memory)和调用数据(calldata)这三种,它们各自有着不同的特性和使用场景,它们的选择会直接影响存储方式和访问成本。

但是很多小白搞不清楚它们的正确用法以及如何区分,下面我们来详细说明一下:

概述

在 Solidity 中,正确的数据存储位置不仅关系到合约的执行效率,还直接影响交易成本(gas)。

存储 storage定义:永久存储在区块链上的变量。适用场景:

contract StorageExample {
    uint256 public value; // 存储在 storage 中
    function setValue(uint256 _value) public {
        value = _value; // 修改 storage 变量,需支付 Gas
    }
}

内存 memory定义:临时存储在内存中的变量,仅在函数调用期间存在。适用场景:

contract MemoryExample {
    function add(uint a, uint b) public pure returns (uint) {
        // 函数参数 a 和 b 存储在 memory 中
        // 局部变量 result 也存储在 memory 中
        uint result = a + b;
        return result;
    }
}

调用数据 calldata定义:专用于 external 函数的输入参数,存储在调用数据中。适用场景特性

function updateName(string calldata _name) external pure returns (string memory) {
    return _name; // 只能读取 _name,不能修改
}

storage、memory 与 calldata 的对比

为了方便大家更直观清晰的区分它们之间的区别,这里整理了一个表格:

存储位置持久性适用范围修改成本

storage

持久存储

状态变量、全局变量

memory

临时存储

局部变量、传递数据

calldata

只读存储

外部函数饿输入参数

常见问题及优化状态变量存储成本高易混概念 stack

像我刚刚学习的时候,就很分不清 storage、memory、calldata 与 stack 有什么区别,到底 stack 应该怎么用呢?

在 Solidity 里,Stack(栈)是 EVM(以太坊虚拟机)用来管理函数调用和临时数据的一种后进先出(LIFO)数据结构。它是一种重要的数据存储机制,主要用于临时存储和计算中间值。

特性256位(32字节)宽度:每个栈元素固定为 32 字节(兼容 EVM 的 256 位字长)。1024 深度限制:栈最多容纳 1024 个元素,超出会触发栈溢出(Stack Too Deep错误)。高效:栈操作非常快速,因为只需在栈顶进行插入和弹出临时性: 栈中的数据仅在当前执行上下文中有效,执行结束后自动销毁用途栈的典型问题与解决方案Stack Too Deep 错误

当函数局部变量或表达式复杂度超过16 个栈槽时,编译器会报错。

function tooManyVariables() public pure {
    uint256 a; uint256 b; uint256 c; // ... 超过 16 个变量
}

修复方案:

2. 优化 gas 消耗

栈操作直接影响 gas 成本:

// 优化后:复用计算结果uint256 sum = a + b;uint256 x = sum;uint256 y = sum;

 - 使用内联汇编:手动控制栈操作(需谨慎)

function optimizedAdd(uint256 a, uint256 b) public pure returns (uint256) {assembly {let result := add(a, b)mstore(0x80, result) // 存储到内存}}


### 栈与内存、存储的对比
| 特性         | Stack   | Memory      | Storage  |
| ---------- | ------- | ----------- | -------- |
| **作用域**    | 当前执行上下文  | 函数执行期间      | 合约生命周期     |
| **Gas 成本** | 最低(纯计算) | 中等(临时扩展)    | 最高(链上存储) |
| **访问速度**   | 最快      | 快           | 慢        |
| **容量限制**   | 1024 元素 | 动态扩展(需 Gas) | 无硬性限制    |
|**持久性**|非持久化|非持久化|持久化|
| **适用场景**   | 操作数和中间结果 | 临时复杂数据存储 | 持久化变量    |

使用本文
0
共享
上一篇

UNISWAP团队转移资金至Coinbase Prime,为何市场反应冷淡?

下一篇

【solidity基础】一文说清楚合约函数的大小事

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

阅读下一页

在以太坊最新的长期测试网

本文概述了以太坊核心开发者在2025年4月的进展,重点关注Pectra升级的发布、历史过期以及Fusaka升级的范围确定。Pectra升级已在主网上线