9

Today while I was developing a C program a college of mine pointed out that I was doing something wrong.

He said that the code that I was doing which is similar to the code below is wrong, and that you can't define a constant based on another constant. The program ended up working anyway, and I was left wondering if he was right. Is the code below wrong/breaks best practices?

const int num=5;
const int num2=num*2;
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Hunterfang
  • 113
  • 1
  • 6
  • Your code [doesn't compile](https://ideone.com/9GamL7). – Kerrek SB Mar 23 '17 at 00:51
  • In my opinion, `num=5` is already a bad practice. So if you want to become a *good practice* programmer, write `const int num = 5`. Also, why didn't you simply compile the code and interpret the error message? – Iharob Al Asimi Mar 23 '17 at 00:52
  • 1
    It is illegal in file scope. – BLUEPIXY Mar 23 '17 at 00:53
  • @IharobAlAsimi What's the difference other than the spaces? – Barmar Mar 23 '17 at 00:54
  • @Barmar, readability. – Iharob Al Asimi Mar 23 '17 at 00:54
  • It complies just fine with Apple LLVM version 8.0.0 (clang-800.0.42.1). – lhf Mar 23 '17 at 00:55
  • @IharobAlAsimi I agree that spaces are nice, but it's really just a programming style issue. I know some very good programmers who like to cram their code together like that. – Barmar Mar 23 '17 at 00:56
  • @KerrekSB: It compiles with Clang (the "C" option on ideone), so I think a definitive answer from the spec is necessary. https://ideone.com/YEjKil – indiv Mar 23 '17 at 00:57
  • @Barmar, I understand, and my opinion is of course subjective. But it simple makes no sense to write `num=5` when you can write `num = 5`, in my opinion, because the compiler can easily tokenize the former, but humans have more difficulty. But then again, it's just my opinion, and many of the bad/good practice advice are just that, opinions too. – Iharob Al Asimi Mar 23 '17 at 00:58
  • 1
    @indiv: Hm, maybe related: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53091 – Kerrek SB Mar 23 '17 at 01:04
  • 1
    "[...] said that the code [...] similar to the code below is wrong". What EXACTLY does the compiler say? Copy&paste the output. Also, how "dissimilar" are both codes (the actual compiled and the one presented)? – rslemos Mar 23 '17 at 01:05
  • @rslemos The compiler doesn't say anything, because as I said the program works. I was just left wondering if this code was somehow wrong because my colleague was very adamant about it being wrong. – Hunterfang Mar 23 '17 at 01:13
  • 1
    Works for C++, not for C. http://stackoverflow.com/questions/4486442/how-does-const-differ-in-c-and-c – B. Wolf Mar 23 '17 at 01:19
  • `num` is not a constant. – chux - Reinstate Monica Mar 23 '17 at 01:23
  • in LLVM, even compiled with `cc -ansi` the 'const' goes into stack – Marco Munari Mar 23 '17 at 01:55
  • Are these back to back lines in your code or "num" is defined in different file? – Swanand Mar 23 '17 at 03:22

2 Answers2

10

These are not constants; they are int variables with a const qualifier. The const qualifier means that the variable cannot be written to by the program. Examples of actual integer constant expressions include 5, 2 + 3, and sizeof(int). Here is a full list.

At file scope the second line is a constraint violation, because the name of a variable is not a constant expression. The constraint is C11 6.7.9/4:

All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.

(variables declared at file scope have static or thread storage duration).

At block scope the code is OK, because initializers do not need to be constant expressions there.

M.M
  • 138,810
  • 21
  • 208
  • 365
5

The classic way to achieve this in C (as you probably know) is to write

#define NUM  5
#define NUM2 (NUM*2)

There are parentheses around the expression, but no semicolons at the end of the lines, because the preprocessor expands the macros as simple lexical substitution. So, the expression 20/NUM2 would expand to 20/(5*2). Without parentheses, it would have been 20/5*2, which is wrong.

Incidentally, in C++, you can use constexpr to get the behavior you want; a constexpr variable can be used in a static initializer or template parameter.

Davislor
  • 14,674
  • 2
  • 34
  • 49