5

Just a general question about programming: When you define a value in C (or any language I suppose), How does the compiler known how to treat the value? For example:

#define CountCycle  100000

I would assume CountCycle is a "long integer" data type, but that's just an assumption. I suppose it could also be a float, a double (not an int as it maxes out at ~32k), etc.

How does the compiler choose the data type for a #define value? I have no application for the answer to this question; I'm just curious.

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
Diesel
  • 519
  • 1
  • 6
  • 24
  • 3
    The compiler doesn't care about `#define` directives at all. It's the preprocessor's job. And the preprocessor knows nothing about types: it merely does text substitution. – ForceBru Aug 31 '17 at 13:22
  • 3
    A define is literally a text replacement, so it's an integer literal in this case. – Hatted Rooster Aug 31 '17 at 13:23
  • 2
    The question perhaps belies a misunderstanding. Within the `#define` the value doesn't have a type, it is just a token. Only when you use it in "real code" does it take a type, and that would be the same type as if you used the literal value. – davmac Aug 31 '17 at 13:23
  • Read more about it at https://www.tutorialspoint.com/cprogramming/c_constants.htm –  Aug 31 '17 at 13:28
  • 1
    Even if it doesn't matter in this particular case, be aware that C and C++ are two very different languages and the tags shouldn't be used together usually. – muXXmit2X Aug 31 '17 at 13:30
  • 1
    @muXXmit2X: By sheer coincidence, the languages have not diverged on this point. – Bathsheba Aug 31 '17 at 13:30
  • It would be rare to find a compiler on a modern platform where int maxes out at 32k. – Retired Ninja Aug 31 '17 at 13:33
  • 1
    @RetiredNinja: I'm not so sure about that, if you put the embedded systems programmers into the mix. – Bathsheba Aug 31 '17 at 13:35
  • You should prefer `const` or `constexpr` variables to defines. – Ron Aug 31 '17 at 13:37
  • 1
    @Bathsheba Hmm, yeah, maybe. Even the embedded stuff we occasionally work on is 32-bit nowadays, but I may be spoiled. :) – Retired Ninja Aug 31 '17 at 13:37

5 Answers5

12

The compiler does no such thing. The preprocessor substitues 100000 for CountCycle.

Once that substitution has been completed, the compiler can take over. 100000 has the type int if it can fit in that range, a long if it can't.

See a C++ Reference and a C Reference.

Noel Widmer
  • 4,444
  • 9
  • 45
  • 69
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

CountCycle does not have a type. It can be substituted for the integer constant 100000 by the preprocessor everywhere in the program where this name is encountered.

It is the integer constant 100000 that has a type.

If an integer decimal constant does not have a suffix then (The C Standard, 6.4.4.1 Integer constants)

5 The type of an integer constant is the first of the corresponding list in which its value can be represented.

int
long int
long long int

If you want that the constant had the type long int you could specify a suffix. For example

#define CountCycle  100000l

if the value of the constant is in the domain of the type long int then the constant will have the type. Otherwise it will have type long long int.

If you want to specify a floating constant you should use one of its representations. For example

#define CountCycle  100000.0
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    Not _everywhere_. E.g. `std::cout << "CountCycle = " << CountCycle;`. Only the second occurrence is replaced. The first occurrence is within a string literal. (cf. UNIX shell scripting, where quotes do not prevent variable replacement) – MSalters Aug 31 '17 at 14:19
  • @MSalters Everywhere. Your example does not show a preprocessor name. – Vlad from Moscow Aug 31 '17 at 14:31
  • 1
    `It is substituted for the integer constant 100000` No, it's substituted as an untyped token, not an integer constant. Where that token get substituted into determines whether or not it gets treated as an integer constant. – underscore_d Aug 31 '17 at 14:52
  • @underscore_d Iupdated the phrase like "it can be substituted..." – Vlad from Moscow Aug 31 '17 at 14:56
0

No research behind this, but I think it probably has to do with where/how you use the #define value. If you have #define MAX 9 for example, and use it to represent the length of an array like people[MAX], the compiler probably interprets MAX as an int. but if you use a placeholder to place it in a string as a char, then it probably interprets it as a char.

jahmiamor
  • 1
  • 2
  • Macros are not C objects and thus don't have a type. They are used by preprocessor to do *text substitution* in source file *before compilation*. Check another answers to this question. – YurkoFlisk Jul 21 '22 at 03:29
-1

There are four stages for a C program to become an executable:

  1. Pre-processing
  2. Compilation
  3. Assembly
  4. Linking

The "Pre-processing" is the first stage.

"#define" is a preprocessor which process before compilation. You create macros with the #define directive. #define is followed by the name of the macro and then the token sequence it should be an abbreviation for, which is variously referred to as the macro's body, expansion or replacement list.

For example-

If you specify the following in your program

#define BUFFER_SIZE 1000

The preprocessor will replace the macro name BUFFER_SIZE with macro expansion 1000 in your source code file before handing it over to the compiler.

H.S.
  • 11,654
  • 2
  • 15
  • 32
-1

The compiler does no such thing. The preprocessor substitues 100000 for CountCycle.

It's true, but you have to care about some compiler options that truncates the value defined. For example, if you are working with an embedded plataform that can't do floating point calc at run time, the compiler maybe implicit converts your float definition for an integer definition. Anyway, you can do flating point math in compiler time. Why? Because many paramethers can increase the final result precision by do this calculation, and you can use the final result truncated in run time.

So, the correct way to use it is to take care in where you use: in the middle of a fixed point math; as floating data; or something else. A good way to prevent erros is explicit casting any numer, by do something like:

#define MY_FLOAT_DATA   (float)4.55
#define MY_INTEGER_DATA (int)4
wnoliveira
  • 31
  • 1
  • 6
  • I'm not sure I agree with any of this. If your embedded platform doesn't support flating [sic] point math then it's not a C or C++ compiler and any deviation from the standard will be documented, and you would program accordingly. – Bathsheba Aug 31 '17 at 18:56