1

Here is the sample code:

#include <iostream>
#include <stdlib.h>
#include <cstdio>

int add(int x, int y){
    return x + y;
}

int main(){
    int x = 10;
    int y = 10;
    if(add(x, y) == 20){
        printf("Here I am\n");
    }

    return 0;
}

I make a comparison between constant value 20 and the returned value of add()(without saving the returned value in a local variable). I was wondering is it safe to do that in c++?

My argument is that if we don't store the returned value back in the stack frame of main(), the returned value literally doesn't exist in the stack and it is only stored in the register like %eax, what if the value stored in %eax is edited before the comparison is made, then the program would probably go wrong.

Below is part of the assembly of the code block: enter image description here

Zijian XU
  • 11
  • 2
  • 2
    No there is no problem here and doing such things are normal. The compiler creates a temporary variable that lives long enough for the comparison. Also, your assumption is wrong that the value does not exist on the stack or that it is only in a register. That is up to the compiler how the value is saved and if it is only in a register the compiler needs to ensure that the register is definitely not edited. Normally you don't need to worry about stack frames and registers anyway. – RoQuOTriX Sep 01 '22 at 06:11
  • 2
    The language standard says nothing about the "stack" or "stack frame". It doesn't define where these objects are stored. It only guarantees that the code will work, because of the lifetime of temporary objects. There could never be an issue; a register's value is not going to get overwritten unless the compiler generates intervening code that overwrites that register's value, and it is not going to do that unless it has a serious code-generation bug. – Cody Gray - on strike Sep 01 '22 at 06:15
  • I see, thanks to RoQuOTriX and Cody Gray – Zijian XU Sep 02 '22 at 06:52

1 Answers1

1

Yes, this is perfectly safe.

When you call a function, its return value becomes a temporary object in the caller's scope. Such temporary objects' lifetime extends to the end of the full expression in which they were created, which is the expression add(x, y) == 20 in this case. Thus it is guaranteed to live long enough for the comparison to be done.


As an aside, I would recommend not thinking about the stack and registers when writing C++. Those things don't exist as far as the C++ language standard is concerned. Instead think about object lifetimes, which are specified by the language. Even on a real implementation, a named variable doesn't necessarily mean the object will ever be stored in memory. The compiler decides where and how to store objects, and it will often store an object purely in registers if it can get away with it, or it may not store them at all if it knows it doesn't need them. Indeed, on any competent modern optimizing compiler, your entire program will likely be reduced to something like

mov edi, OFFSET_OF_STRING_CONSTANT
call printf
xor eax, eax
ret

Since the compiler knows the values of x and y and add is simple enough that it can determine the result of the comparison at compile time and avoid emitting any code for that call or comparison at all. Compiler Explorer example.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52