What does C(++) do with values that aren't sto

2020-06-08 13:33发布

问题:

I'm a bit curious about how C and C++ handle data which isn't stored in variables, e.g:

int IE6_Bugs = 12345;
int Win_Bugs = 56789;

Yeah - everything clear. IE6_Bugs has 123456 stored at it's specific memory address.

Then what about..

if ( IE6_Bugs + Win_Bugs > 10000 )
{
  // ...

So C grabs the values of the two variables and adds them in order to compare the result to the int on the right.

But:

  • Does IE6_Bugs+Win_Bugs ever reach RAM? Or does the processor directly compare the values via its own cache?

  • Or is, in the compiling process, the above if statement converted to something more "understandable" for the machine? (Maybe calculate IE6_Bugs+Win_Bugs first and store it in some variable,...)

回答1:

It'll be placed in a register in the CPU (assuming one is available). A register is a sort of super-fast super-small RAM that's built into the CPU itself and used to store results of intermediate operations.

If the value can be determined to always equal xxx then a smart compiler will substitute the value of xxx in its place.

Keep in mind that regardless of whether it is as an expression or a number, (x+y vs 10) it will still need to be placed in a register so that the CPU can access it and perform an operation based on its value.

For more info, read up on computer architecture.



回答2:

In the general case, the code generator encodes such values directly in instructions ("immediate-mode addressing") or stores them in the program's data segment to be loaded as needed.

An optimization known as "constant folding" computes the values of constant expressions at compile time. In your particular example, a smart compiler will recognize that your condition will always be true and avoid generating code for the test, so the values 12345, 56789, and 10000 may not be represented at all in the machine code generated for your program.

Your compiler likely has an option to preserve the intermediate assembly-language generated for your program, e.g., g++ -S. Learn a bit about your processor's architecture and assembly language to learn to make sense of and even helpful inferences from this output.



回答3:

Well, a good compiler will do constant propagation and folding, so in that example, it'd replace IE6_Bugs with 12345 and Win_Bugs with 56789, and then convert that into 69134. It would then probably also fold 69134 > 10000 to 'true' and remove the branch altogether, all at compile time.

As for where it would store the result of the expression if it didn't do constant propagation or folding, either a memory location, or a register. A register will be much faster.



回答4:

It puts nameless temporary values wherever it puts named variables - typically on a stack. And as with named variables, the compiler may choose to place the values in CPU registers to speed things up. If you are really interested in this, you should have a look at the assembler output generated by your compiler.



回答5:

There is absolutely no way to conclusively answer this question. The other answers here are accurate for most architectures, but this is not in any specified by the C/C++ standards, which are hardware agnostic.

The order of evaluation is defined by the standard. How things are eventually handled in memory is not.



回答6:

The way to tell is to inspect the generated assembler code, or step through it in a debugger. Different compilers may do it in different ways. It might also depend on your compiler options, such as "DEBUG."

The comments here about constant folding and the elimination of the "if" test would apply if the declarations were prefixed with "const."