16

Why in solidity, i++ & ++i works the same but one costs a little bit more gas?

Take a look at this contract:

contract foobar {
uint[] public arr = [1,2,3,4,5];

function find() public view returns(bool) {
        for(uint i = 0; i < arr.length; i++ /*++i*/) {
        if(arr[i] == 5) {
            return true;
        }
    }
    return false;
}

}

When I run this contract using i++ this is what the contract's cost is:

// i++
// gas  388824 gas
// transaction cost 338107 gas 
// execution cost   338107 gas 
// foobar.find() execution cost 36221 gas

And when I run the same function using ++i, this is what the cost is:

// ++i
// gas  388327 gas
// transaction cost 337675 gas 
// execution cost   337675 gas
// foobar.find() execution cost 36201 gas

Clearly, i++ costs more gas than ++i, But Why? Thanks

DevABDee
  • 441
  • 2
  • 11
  • 5
    Pre-increment and post-increment usually result in slightly different execution steps, this is not unique to Solidity. Related: What is the difference between ++i and i++? – Mast Aug 07 '22 at 18:18
  • 1
    Newer versions of solidity should optimize this. In the past, the difference could be attributed to the codegen for i++ not getting inlined. Try --via-ir with the optimizer, they should have identical gas cost, except when the semantics are different. – hrkrshnn Aug 09 '22 at 18:28

1 Answers1

29

They do not work the same. i++ gets compiled to something like

j = i;
i = i + 1;
return j

while ++i gets compiled to something like

i = i + 1;
return i;

Long story short, i++ returns the non-incremented value, and ++i returns the incremented value, so for example, doing

i = 0;
array[i++];

will access the value at index 0 in the array, while array[++i] will access the value at index 1.

Foxxxey
  • 4,307
  • 1
  • 6
  • 22
  • 3
    +1 for "They do not work the same.". [Too] Many people make this mistake. – Phill W. Aug 08 '22 at 11:27
  • 8
    Though you'd expect most modern compilers to be able to automatically optimise i++ into the same operations as ++i if the value of the expression is not actually being used like in the OPs example... – Sean Burton Aug 08 '22 at 11:44
  • 2
    this is the kind of thing an optimizing compiler could reasonably be expected to optimize tho.. for example gcc auto-optimize this on -O2 and -Og but not -O0 - notably the PHP language does not optimize this at all (: – hanshenrik Aug 08 '22 at 13:21
  • 5
    Relevant Google-able terms are "prefix operator" (++i) and "postfix operator" (i++) operator. For completeness: there's also an "infix operator" (i + 1). – minnmass Aug 08 '22 at 13:48
  • 3
    @SeanBurton does Ethereum use dumb compilers on purpose for security? optimizations have created wrong code and security vulnerabilities before – user253751 Aug 08 '22 at 13:51
  • 2
    @user253751 Compilers almost never create wrong code. Any industrial grade compiler will have gone through so much testing and real-world use, it is practically impossible for it to produce code that behaves differently than the unoptimized version. The reason you hear about security issues due to optimization is when C/C++ developers invoke Undefined Behavior, in which case all behavior is undefined, optimizations or not (tho -O3 is much more likely to bring demons). You never hear about security issues with optimization in languages like Java or LuaJIT, with advanced optimizers. – Carson Graham Aug 08 '22 at 18:26
  • 1
    @CarsonGraham yeah, but sometimes they do and you really don't want that happening when billions of dollars of un-rollback-able transactions are involved. – user253751 Aug 08 '22 at 18:41
  • 2
    The main time that optimisations can be really problematic for security (assuming they're not bugged/broken) are when trying to write constant-time code and it's replaced by an optimisation that isn't constant-time. But since all values being used by a contract are visible on the blockchain, you're never going to be directly processing anyone's private keys or secret values in Solidity, so there's probably no need for any Solidity code to be constant-time. – Sean Burton Aug 09 '22 at 12:38
  • 2
    Well, as someone said in the main post comment's, solidity can optimize this now. so, yea. Sean is definitely right - time complexity optimization is a big issue with writing secure code when doing things like validating sensitive information. Related, I think it's very funny that Ethereum developers have made it so expensive to write code, but basic space optimization is hard to come by, when it would save so much money. Very funny – Carson Graham Aug 09 '22 at 20:17