2

When you call a function, arguments that are passed to the function are passed-by-value if they are not arrays or not deliberately passed-by-reference with the ampersand (&) symbol. For instance,

void boo (int a, int b) {}

int main() {
    int var1 {1};
    int var2 {2};

    boo(var1,var2);

    return 0;
}

In this scenario, values of the integer variables var1 and var2 are copied to the function parameters a and b and stored in the stack frame allocated for the boo() function. My questions are:

If I write

void boo (int a, int b) {}

int main() {
    boo(1,2);

    return 0;
}

are the integer literals 1 and 2 not stored in the main() stack frame since they are now r-values?

If I instead write

void boo (int &a, int &b) {}

int main() {
    int var1{1};
    int var2{2};

    boo(var1,var2);

    return 0;
}

are the parameters a and b still stored in the stack frame of the boo() function as a some kind of a back-up etc. Or are they only references to the actual parameters var1 and var2 now?

Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
  • **Comments have been [moved to chat](https://chat.stackoverflow.com/rooms/252522/discussion-on-question-by-conventionalprogrammer-stack-allocation-in-a-function); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed. – blackgreen Mar 14 '23 at 22:52

1 Answers1

5

The code you write is not instructions for your cpu. It is instructions for your compiler. After reading this answer you might argue that your code was just a simplified example, but same as your compiler I can only work with what you provide. The compiler turns your code into machine instructions that have the observable behavior as specified for your code in the c++ standard.

Your code:

void boo (int a, int b) {
}

int main() {

    int var1 {1};
    int var2 {2};

    boo(var1,var2);

    return 0;
}

Has exactly the same observable behavior as this one:

int main() {}

The integer literals must not be stored anywhere. They need not even appear in the executable binary. The same is true for the other code examples in your code. For more details I refer you to What exactly is the "as-if" rule? and Storage of literal constants in c++.


For the sake of illustration, consider a different example:

int main() {
    return [](int x){
        int sum = 0;
        for (int i=0;i<x;++i) sum += i;
        return sum;
    }(5);
}

Rather than discussing it on a language-lawyer basis, I hope it suffices as demonstration that gcc with optimizations turned on procudes the following output:

main:
        mov     eax, 10
        ret

The literal 5 is not stored anywhere. If you like you can experiment with passing int x = 5; to the lambda, it will not make a difference. As PaulMcKenzie mentions in a comment, you can turn the lambda with the loop into a recursive function and you will still see the same effect: No 5 anywhere.

Gcc correctly realized that the observable behavior of the above code is (in plain english terms): "return 10 from main", hence it produced output that does that. Now you ask "where is the 5 stored?" But the code is just a convoluted way to describe returning 10 from main and that needs no 5 stored anywhere.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Oh... I think that there is a confusion resulting from the edit of @273K. I firstly written */ Some code here /* comments in the code. In other words, I assumed there were implicit operations like int c {}; c=a*b; etc. in the body of the function – ConventionalProgrammer Mar 14 '23 at 18:18
  • 2
    @ConventionalProgrammer with comments along the line of `/* some code */` I would have written this answer no different. Comments are not code. My point is that the output of the compiler depends on the details you left out. – 463035818_is_not_an_ai Mar 14 '23 at 18:20
  • @ConventionalProgrammer consider this example https://godbolt.org/z/n6jWh411K. 2 integer literals, 1 is passed to a function. In the output of the compiler there is not even a function call left over. Optimizations are not guaranteed. Changing a tiny detail or compiler flags can change the output of the compiler completely, but the behavior will always be the same: It returns 10 – 463035818_is_not_an_ai Mar 14 '23 at 18:26
  • 1
    ... and thats what matters. The code is an abstract descpription of the runtime behavior. When you write in main `return foo(5);` and `foo(5)` will return 10, then it does not matter where 5 is stored of if its stored at all as long as the program will return 10 from main – 463035818_is_not_an_ai Mar 14 '23 at 18:28
  • Thank you for your explanatory answer. – ConventionalProgrammer Mar 14 '23 at 18:34
  • @463035818isnotanumber One last question, when 10 is returned, isnt it returned as an r-value? In the assembly there does not occur a "5" but there occurs a "10" anyways. Shouldn't this "10" be stored now? – ConventionalProgrammer Mar 14 '23 at 18:59
  • @ConventionalProgrammer the term "r-value" has a meaning in c++ code not in assembly. – 463035818_is_not_an_ai Mar 14 '23 at 19:05
  • @ConventionalProgrammer are you perhaps refering to "the address of r-values can be taken" as eg explained here https://en.cppreference.com/w/cpp/language/value_category ? If you never take the adress you cannot tell the difference whether something has an adress or not. Its the as-if rule. What matters is observable behavior. – 463035818_is_not_an_ai Mar 15 '23 at 08:20
  • @ 463035818isnotanumber I think that rvalues has not a meaning in assembly is a good explanation. At least it appears to me. When I write C++ code, I am always bothered about where they are stored, if they are even stored. However, after seeing your Assembly code example, I see that a lot of details about the integer literals in C++ code are optimized away by the compiler. What is returned or moved into registers are now integers in the Assembly code. In C++ code, integer literals ain't nothing but texts that probably live in the code segment. – ConventionalProgrammer Mar 15 '23 at 11:04
  • @463035818isnotanumber I think that my main confusion is the definiton of "storage". Literally everything I write as a code must live in computer's memory somewhere at least for a specific amount of time. After compilation by the compiler, I guess that the compiled code live in what they refer to as "Code segment" of the memory. However, some values can be stored into variables which live in (or 'stored' in) different virtual memory portions other than the code segment. In the case of integer literals, I now think that their values are directly loaded inline with their binary representations. – ConventionalProgrammer Mar 15 '23 at 11:47
  • @ConventionalProgrammer "Literally everything I write as a code must live in computer's memory somewhere at least for a specific amount of time" yes that (and what follows) is a misunderstanding. As I wrote, code you write is **not** instructions for the hardware. It is instructions for the compiler to generate instructions for the hardware. The c++ language is defined in terms of an abstract machine and its observable behavior. After you compiled the code, the source is not that relevant anymore – 463035818_is_not_an_ai Mar 15 '23 at 12:05
  • @ConventionalProgrammer I think what you are looking for is something like this https://godbolt.org/z/MMsGYfccP. Note the difference between `x` and `y`. And note how I had to push the compiler to not eliminate `x` from the output – 463035818_is_not_an_ai Mar 15 '23 at 12:06
  • @463035818isnotanumber In this case, the x is an integer constant, which is a non-modifiable l-value. My main problem was the portion '42' itself. Especially in the case where it is not assigned to anything etc. By the way, thank you for your patient answers so far. Note: "...yes that (and what follows) is a misunderstanding..." -- Does that mean what I wrote was wrong on the comment above? – ConventionalProgrammer Mar 15 '23 at 12:18