18

I'm somewhat confused by #define statements. In libraries, they seem to be a means of communication across different files, with lots of #ifdefs and #ifndefs.

Having said that, I now have two files file1.c and file2.c compiled together, with #define TEST 10 inside file2.c. Yet, when I use TEST inside file2.c the compiler gives the following error message:

'TEST' undeclared (first use in this function) 

Are #define directives global?

3
  • It depends where they are defined. Commented May 9, 2012 at 9:01
  • #define is a preprocessor directive - it just makes simple text substitutions at compile time - only the compilation unit and any #included files will see a #define. Commented May 9, 2012 at 9:02
  • the (#ifndef #define #endif) trick would not work if macros were global Commented Jan 21, 2024 at 7:26

4 Answers 4

24

#defines are not global, they are just a substitution where ever they are used (if declared in the same compile unit)

They are not globals, they are not symbols, they are irrelevant at linkage, they are only relevant at pre-compilation.

Sign up to request clarification or add additional context in comments.

5 Comments

What do you mean by "compile unit"? How can I have file1.c and file.2 in the same compile unit?
No. they are compiled separately. and hen linked together. Are you familiar with the C build process?
So file1.c and file2.c can never be in the same compile unit?
basically - no. if you want to share a macro between them, put it in a header file and include that header in both files.
@Randomblue: Think of a "compile unit" as "a c file, and all of the headers it includes, and all of the headers those include, etc, etc, etc, until no more headers". This is one "chunk" that the compiler compiles. After the compiler compiles each c file separately, then it links those outputs togeather.
11

#defined macros are global in that they do not follow normal C scoping rules. The textual substitution from the macro will be applied (almost) anywhere the macro name appears after its #define. (Notable exceptions are if the macro name is part of a comment or part of a string literal.)

If you define a macro in a header file, any file that #includes that header file will inherit that macro (whether desired or not), unless the file explicitly undefines it afterward with #undef.

In your example, file2.c does not know about the TEST macro. How would it know to pick up the #define from file1.c? By magic? Since macros perform textual substitution on the source code, there is no representation of them in the generated object files. file2.c therefore needs to know that substitution rule itself, and if you want that shared across multiple files, that #define needs to live in a common header file that your .c files #include.

If you're asking specifically about how many of the #ifdefs that you see in libraries work, many of them are likely checking against pre-defined macro names provided by the compilation environment. For example, a C99 compiler defines a __STDC_VERSION__ macro that specifies the language version; a Microsoft compiler defines an _MSC_VER macro. (Often these predefined macros start with leading underscores since those names are reserved for the compiler.)

Additionally, most compilers allow defining simple macros as command-line arguments. For example, you might compile your code via gcc -DNDEBUG file1.c to compile file.c with NDEBUG defined to disable asserts.

1 Comment

Thx for helpful info
2

In case somebody reads this later, and to add some practical information:

  • Some environments like atmel, vs, or iar, allow you to define global #define directives. They basically pass these defined values to the precompiler in some commandline format.
  • You can do the same in batch commands or makefiles, etc.
  • Arduino always adds a board variant (usually located at hardware\arduino\variants) to all compilations. At that point you can create a new board that contains your global define directives, and use it that way. For example, you can define a mega2560(debug) board out of the original mega2560 that contains some debug directives. You will add a reference to that variant in "boards.txt", by copy pasting some text, and properly modifying it.

At the end of the day, you will have to give that global hfile or global directive to the compiler in one way or another.

Comments

0

you should make a file1.h and put your defines there. Then in file2.c

#include "file1.h" 

easy as a pie :)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.