Type of #define variables

If I have:

#define MAXLINE    5000

What type is MAXLINE understood to be? Should I assume it is an int? Can I test it somehow?

In general, how can one determine the type of #defineed variable?


Solution 1:

It has no type. It is a simple text substitution. The text 5000 will be dropped in place wherever MAXLINE appears as a token.

For example:

int a = MAXLINE;

will put the value 5000 in a.

While

char *MAXLINE2 = "MAXLINE";

will not result in

char *50002 = "5000";

So, if you want type-checking, macro's are not the way to go. You will want to declare static constants instead, that way type-checking is done by the compiler.

For information on the differences between static, const, and #define, there are many sources, including this question: Static, define, and const in C

Solution 2:

(Very!) Broadly, your C compiler is going to perform 3 tasks when executed:

  1. Run a preprocessing pass over your source files,

  2. Run a compiler over the preprocessed source files

  3. Run a linker over the resulting object files.

Lines starting with a #, like the line


#define MAXLINE    5000

is handled by the preprocessor phase. (simplistically) The preprocessor will parse a file and perform text substitutions for any macros that it detects. There is no concept of types within the preprocessor.

Suppose that you have the following lines in your source file:


#define MAXLINE    5000
int someVariable = MAXLINE;     // line 2
char someString[] = "MAXLINE";  // line 3

The preprocessor will detect the macro MAXLINE on line 2, and will perform a text substitution. Note that on line 3 "MAXLINE" is not treated as a macro as it is a string literal.

After the preprocessor phase has completed, the compilation phase will only see the following:


int someVariable = 5000;        // line 2
char someString[] = "MAXLINE";  // line 3

(comments have been left in for clarity, but are normally removed by the preprocessor) You can probably use an option on the compiler to be able to inspect the output of the preprocessor. In gcc the -E option will do this.

Note that while the preprocessor has no concept of type, there is no reason that you can't include a type in your macro for completeness. e.g.


#define MAXLINE    ((int)5000)

Solution 3:

the compiler never sees that line of code, a preprocessor runs before the actual compilation and replace those macros with their literal values, see link below for more information

http://www.cplusplus.com/doc/tutorial/preprocessor/

Solution 4:

It has no type. It's just a token which the preprocessor will put into the source code before passing the code to the compiler. You can do this (ridiculous) thing to declare a variable called x5000:

#define APPEND(x,y) x ## y

int main() {
        int APPEND(x,5000);
        x5000 = 3;
}

The preprocessor turns that into this before passing it the compiler proper:

int main() {
        int x5000;
        x5000 = 3;
}

So, just because you see 5000 in a macro, it doesn't mean it needs to be numeric in any way.

Solution 5:

MAXLINE is not a variable at all. In fact, it is not C syntax. Part of the compilation process runs a preprocessor before the compiler, and one of the actions the preprocessor takes is to replace instances of MAXLINE tokens in the source file with whatever comes after #define MAXLINE (5000 in the question's code).

Aside: another common way you use the preprocessor in your code is with the #include directive, which the preprocessor simply replaces with the preprocessed contents of the included file.

Example

Let's look at an example of the compilation process in action. Here's a file, foo.c, that will be used in the examples:

#define VALUE 4

int main()
{
  const int x = VALUE;
  return 0;
}

I use gcc and cpp (the C preprocessor) for the examples, but you can probably do this with whatever compiler suite you have, with different flags, of course.

Compilation

First, let's compile foo.c with gcc -o foo.c. What happened? It worked; you should now have an executable foo.

Preprocessing only

You can tell gcc to only preprocess and not do any compilation. If you do gcc -E foo.c, you will get the preprocessed file on standard out. Here's what it produces:

# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo.c"


int main()
{
  const int x = 4;
  return 0;
}

Notice that the first line of main has replaced VALUE with 4.

You may be wondering what the first four lines are. Those are called linemarkers, and you can read more about them in Preprocessor Output.

Compilation without preprocessing

As far as I know, you cannot outright skip preprocessing in gcc, but a couple approaches exist to tell it that a file has already been preprocessed. Even if you do this, however, it will remove macros present in the file because they are not for compiler consumption. You can see what the compiler works with in this situation with gcc -E -fpreprocessed foo.c:

.
.
.
.
int main()
{
  const int x = VALUE;
  return 0;
}

Note: I put the dots in at the top; pretend those are blank lines (I had to put them there to get those lines to be displayed by SO).

This file clearly will not compile (try gcc -fpreprocessed foo.c to find out) because VALUE is present in the source, but not defined anywhere.