-4

I am rewriting a function and I noticed one particular variable is never reassigned after initialization. Is there any reason NOT to simply convert this variable to a macro? Is a macro ALWAYS preferable in this case?

Thanks!

Eman
  • 6,383
  • 4
  • 23
  • 29
  • 4
    It's preferable to use a `const` over macro. – Eugene Sh. Sep 28 '16 at 21:47
  • Is the initializer a constant value or an expression? I agree with the consensus that a `const` 'variable' is better, but it is even more pronounced if the initializer is an elaborate run-time expression, especially if the value is used more than once. One additional advantage of not using a macro: the variable name will be in the symbol table of the program, whereas a macro will not be in the symbol table. The absence of a symbol makes debugging harder than it need be. – Jonathan Leffler Sep 28 '16 at 22:09
  • @EugeneSh.: `const i = 10; static int a[i];` does not work! In C you need a clear naming scheme anyway, no specific problem with macros. If you need a symbolic constant, use a macro. I'm with you for function-like macros, though. – too honest for this site Sep 28 '16 at 22:13
  • 2
    This question would be much better if you actually showed the code that you're talking about. – user3386109 Sep 28 '16 at 22:13
  • @Olaf I didn't claim they are completely interchangeable. Recently I've had to switch from `#define` to `const` to avoid a "pointless comparison" warning, as it was comparing the `#defined`constant zero against an unsigned (some version specific information). – Eugene Sh. Sep 28 '16 at 22:19
  • 1
    " Is a macro ALWAYS preferable in this case?" --> the case is not clearly presented. – chux - Reinstate Monica Sep 28 '16 at 22:20
  • @EugeneSh.: You are aware your example actually supports my point, do you? And there are alternatives. On some very low-level OS code, I sometimes also have unavoidable warnings. That's what `#pragma push ... pragma pop` is for. – too honest for this site Sep 28 '16 at 22:21
  • @chux: Nor is a `const` variable. I'd CVed as too broad if I had CVs left (didn't know there is a dup, though). It is just that unreflected macro-bashing which upsets me. – too honest for this site Sep 28 '16 at 22:22
  • @olaf the initial pragma solution was rejected in the code review :) I don't argue your point. I am saying that const is preferable alternative if it is an actual alternative. In case you presented it is not. – Eugene Sh. Sep 28 '16 at 22:25
  • @EugeneSh.: Kick the reviewer where it hurts for being ignorant then;-) I know such ppl, too: just MISRA and nothing else in their head. My personal statement: those ppl don't really know the language, that's why they stick to some simple check-list document. In general, if I need "symbolic" constants, I use `const` in C++ and macros in C (`enums` are often near useless due to their automatically choosen type and the constants being `int`-only). ... – too honest for this site Sep 28 '16 at 22:29
  • @EugeneSh.: ... FYI: on arch like ARM-MCUs, `const` variables have another problem: the compiler can emit load-instructions as they take the same code-space and **theoretically** cycles. For true constants, it generates 16 bit move instructions (upper/lower 16 bits). With a slow Flash and prefetch those are much faster than the loads which stall the prefetch and have to access a completely different part of Flash, with all waitstates included. That easily can add some 10 cycles (for a 150-200MHz CPU) to each load. Quite some time e.g. in an interrupt-handler. – too honest for this site Sep 28 '16 at 22:36
  • You could/should review [`static const` vs `#define` vs `enum`](http://stackoverflow.com/questions/1674032/static-const-vs-define-vs-enum/) — it covers closely related ground even if it doesn't cover exactly your issue. As I noted earlier, a lot depends on the nature of the initialization for the variable. – Jonathan Leffler Sep 29 '16 at 00:26

1 Answers1

-1

A macro is basically never preferable compared to a variable, since a variable which doesn't change its value can be declared as const and it will likely be optimized away in any case.

const int CONST_VALUE = 1234;

is safer and clearly expresses the meaning more than a macro.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • This is not a variable - it cannot vary - hence `const` – Ed Heal Sep 28 '16 at 21:55
  • Please don't suggest UPPERCASE for non macros. Const and non-const variables are lower case. – 2501 Sep 28 '16 at 21:57
  • 1
    It is perfectly reasonable to use UPPER CASE in this instance. It behaves similar to a macro. Does not require memory for the value – Ed Heal Sep 28 '16 at 21:58
  • @2501: It's totally legitimate to use an upper case name for a const variable. – Jack Sep 28 '16 at 21:59
  • 2
    That code above is still a variable in C. Try this at file-level and `int a[CONST_VALUE];`! Macros are the C-way to define symbolic constants. There is nothing wrong with them. – too honest for this site Sep 28 '16 at 22:07
  • @2501: While I agree with you, it is no concrete law. – too honest for this site Sep 28 '16 at 22:08
  • @Olaf: a flaw of the language shouldn't justify using macros to define symbolic constants when you are allowed to use the latter. It's simply bad practice, less safe and totally discouraged. – Jack Sep 28 '16 at 22:10
  • @Jack: That is not a "flaw of the language", but that's how the language is designed. If you are on Rome, speak like a Roman. Trying to enforce programming style for other languages in one language will only result in disaster. There is nothing wrong with such macros if you have a consistent naming scheme (you need that anyway in a mid-to-large C project). – too honest for this site Sep 28 '16 at 22:16
  • @Jack: Please provide a reference to where the standard discourages using constant-like macros. – too honest for this site Sep 28 '16 at 22:18
  • If `CONST_VALUE`, as a `const int`, was not `static` and outside a function, it collides with files that may use the same name for an object. If `CONST_VALUE` was a macro, --> no collision. – chux - Reinstate Monica Sep 28 '16 at 22:18
  • @Olaf: that's not a sensible comparison. The fact that the C specification doesn't allow a non `volatile const` variable which never has its address taken to be optimized away and used to specify the size of an array is a flaw of the specification per se. There is no drawback in using a `const int` instead of a macro, so I don't get how a macro textual replacement could be better than something that is semantically interpreted. – Jack Sep 28 '16 at 22:21
  • @Jack: That is completely unrelated to the `volatile` qualifier! And optimisation shall not change the observable behaviour required by the abstract machine. If your compiler changes behaviour of a program due to optimisations, get your money back! The example is perfectly valid as-is and will not work in C, because `const` qualified **variables** are - well - **variables** and VLAs with static storage duration are not allowed. No offence, but it strongly seems as if you talk from a C++ viewpoint. – too honest for this site Sep 28 '16 at 22:46
  • Indeed in the case of a symbolic constant which is not used to declare an array the observable behavior doesn't change. Any compiler will optimize it away if it's not involved in any edge case (and if it's not `volatile`, which is totally related to the question, since a `volatile const` can't be replaced with its value directly in optimization just because in that case you are effectively changing the observable behavior). Check this code https://godbolt.org/g/9etgnC and tell me how `const int` has changed the observable behavior compared to a `#define`. – Jack Sep 28 '16 at 22:55
  • @Olaf: just to be precise the online compiler is a C++ one because I haven't been able to find the same tool for C language but local results (clang-703.0.31) are exactly the same, compiled with `clang -S -O3 foo.c` – Jack Sep 28 '16 at 23:00
  • 1
    @Jack: If you try this on some embedded systems, you will be surprised. As a general rule, true constants will result in less surprise and - on some (quite common!) targets - can result in much faster code. – too honest for this site Sep 28 '16 at 23:06
  • @Olaf: ok, that's the first reasonable comment I read. Yes, and that's true since C specification treats `const` differently from C++. But this doesn't justify blindly suggesting people to avoid using `const` (at least on x86/64 and arm) in favour of textual replacement (which you agree, is evil by definition). Undoubtedly it is worth warning that a `const int` used for a symbolic constant could require storage according to compiler and architecture (which I consider an edge case, since embedded systems are a requirement not the first case scenario) – Jack Sep 28 '16 at 23:19
  • 1
    @Jack: The problems I mentioned at least very well can apply especially to ARM (something like MSP430 or S08 typically does not have waitstates on memory)! Have a look at the instruction set. So it very well is appropriate to recommend using constant-like macros **in C**! If you use reasonable names (and not `A`, `i`, etc. which is bad style for variables as well), there is no true disadvantage. But you are always on the safe side. – too honest for this site Sep 28 '16 at 23:48