0

What is the difference between doing the following:

const int var1=100;
#define   var2 200

int main(int argc, char* argv[]) 
{

}

Does the var2 occupy an address/value or is it substituted by the compiler? When would one be used over the other?

samuelbrody1249
  • 4,379
  • 1
  • 15
  • 58
  • 1
    `var2` is substituted by the preprocessor before the code gets to the compiler – Eduardo Pascual Aseff Nov 01 '20 at 02:04
  • @NateEldredge thanks that's a helpful link. I don't really understand the accepted answer though, for example: `const in C does not mean something is constant. It just means a variable is read-only.` Doesn't read-only imply something is constant though? Or does that just mean that it may not be constant but is just read-only for **this program** ? – samuelbrody1249 Nov 01 '20 at 03:16
  • 1
    @samuelbrody1249: I think they mean "constant" in the sense of "a value which is known at compile time". You can have `extern const int foo;` in which the case the compiler doesn't know the value of `foo`, and any time you read its value, a memory access is generated, as for any other variable (barring link-time optimization or the like). The compiler will just produce a diagnostic if you attempt to write to `foo` in an obvious way. – Nate Eldredge Nov 01 '20 at 03:29

2 Answers2

1

In your example, var2 is simply text to be replaced by the C preprocessor. Before the program is even compiled, the preprocessor parses the source file and replaces any occurrences of "var2" (that aren't inside comments or string literals) with the expansion text, which in your example is the number 200. It doesn't occupy space in memory because the compiler doesn't even see the "var2", it just sees the numerical constant literal "200".

var1, however, is an unmodifiable lvalue (i.e. it does exist in memory). When you qualify a variable definition with the keyword const, the compiler will throw an error any time the program attempts to modify the variable.

Using macros like #define var2 200 does have performance benefits - namely your program will take less memory (because there are less variables on the stack) and your program may run a bit (maybe negligibly) faster (because the processor doesn't have to always load values in from memory).

However, macros can be error-prone and, except in the most performance-intense applications, the safeguards of using const variables usually outweigh the costs. Still, today's compilers are very smart and can perform optimizations for const variables to even further mitigate the performance costs.

Nasrat Takoor
  • 344
  • 3
  • 8
  • thanks, out of curiosity, what might be an example of `except in the most performance-intense applications,` where that would be a consideration ? – samuelbrody1249 Nov 01 '20 at 02:48
  • 1
    The compiler is not required to give `var1` a specific memory location unless the program takes its address somewhere. And integer literals like 100 and 200 must be placed somewhere, if they are used. So there is no essential difference whatsoever. – rici Nov 01 '20 at 02:54
  • 1
    I would quarrel with this: " It doesn't occupy space in memory because the compiler doesn't even see the "var2", it just sees the numerical constant literal "200"." The constant will most definitely be occupying memory, just in the program's code instead of the stack etc. – PiRocks Nov 01 '20 at 03:22
1

Unless you use the & address-of operator on var1, the compiler is not obliged to give it a fixed address. (Although it probably will, if the variable is defined with external linkage.)

Even if you do take var1s address, the compiler is entitled to substitute a reference to the variable with its known value. So there is no real difference at runtime between the two ways of defining constants.

During the compilation, there is a difference: var2 can be used where the compiler requires a constant, such as a case label or array size, whereas var1 cannot. That has no performance implications, but it might still be a consideration.

Also, integer literals -- if they are used -- must be stored somewhere, even if it is an immediate operand of a machine instruction. Whether that is feasible and beneficial depends on the size of the integer and the machine architecture. It does not depend on whether the constant has a name.

rici
  • 234,347
  • 28
  • 237
  • 341
  • Thanks for this answer. Can't nearly all integer literals be used in the instruction, i.e., `movabsq` allows 64-bit immediate? – samuelbrody1249 Nov 01 '20 at 03:09
  • 1
    @samuel: depends on the instruction and the machine architecture. But if it makes the instruction bigger, then it is equally occupying space. – rici Nov 01 '20 at 03:10
  • oh, I see what you mean now, that makes sense. – samuelbrody1249 Nov 01 '20 at 03:10
  • also, could you please clarify what you mean by `Unless you use the & operator on var1, ` -- for example, why does the require the compiler to give the var a fixed address? – samuelbrody1249 Nov 01 '20 at 03:11
  • @samuel: because `&var1` is the address of `var1`. If you use that address, it must be a fixed value, and there must be a 100 at that address – rici Nov 01 '20 at 03:13
  • got it, sorry I misunderstand, I thought it was the `&` bitwise operator and not the address-of. – samuelbrody1249 Nov 01 '20 at 03:14
  • @samuel: if you want to declare an integer constant, use `static const` so that it doesn't have external linkage. In C++, but not C, that will allow it to be used as a constant at compile-time, too. – rici Nov 01 '20 at 03:20