gas优化用++i还是i++

iszzm123 发布于 2026-05-18 阅读 192

++i(前递增):将i加1,然后直接返回新值。i++(后递增):将i加1,但返回的是旧值。这意味着,i++在执行过程中必须“记住”旧值,等加法完成后再把旧值返回。在EVM中,这个“记住”意味着至少一次额外的栈操作(通常是DUP和SWAP),这些操作虽然单价便宜3gas

++i(前递增):将 i 加 1,然后直接返回新值。

i++(后递增):将 i 加 1,但返回的是旧值。

这意味着,i++ 在执行过程中必须“记住”旧值,等加法完成后再把旧值返回。在 EVM 中,这个“记住”意味着至少一次额外的栈操作(通常是 DUPSWAP),这些操作虽然单价便宜(3 gas),但在循环等高频场景下会累积。

++i 没有这个包袱:它直接加、直接拿结果,不需要暂存旧值。

实际上:

function loopPost(uint n) external pure returns (uint) {
	uint sum;
	for (uint i = 0; i < n; i++) {   // 独立递增,结果没用
		sum += i;
	}
	return sum;
}
function loopPre(uint n) external pure returns (uint) {
	uint sum;
	for (uint i = 0; i < n; ++i) {
		sum += i;
	}
	return sum;
}

在高版本编译器 + 优化器开启下,这两个函数的 gas 消耗几乎完全相同,因为 i++ 的返回值被丢弃,优化器会移除冗余的栈操作。但在早期编译器或未开启优化的场景中,loopPre 仍可能略便宜。

极致的gas优化:

自 Solidity 0.8 起,默认的 ++ 会进行溢出检查(SafeMath 逻辑),这本身也要 gas。如果循环的递增变量不会溢出(例如从 0 到 nn 远小于 2^256-1),可以包裹在 unchecked 块中,连检查的 gas 也省。

for (uint i = 0; i < n; ) {
	// 循环体
	unchecked { ++i; }
}

相关文章

0 条评论