6

The 1 seems unnecessary (and possibly misleading) in the following example, but I have seen this multiple times when used for checking #ifdefs:

#ifndef __NEWLIB_H__ #define __NEWLIB_H__ 1 

Is there a difference or reason for using the above versus a plain #define __NEWLIB_H__?

5
  • 6
    This doesn’t address the question, but names that contain two consecutive underscores (__NEWLIB_H__) and names that begin with an underscore followed by a capital letter are reserved for use by the implementation. Don’t use them in your code. Commented Mar 17, 2020 at 2:34
  • 1
    @PeteBecker Yeah, this code is actually from (or "is") the implementation. Commented Mar 17, 2020 at 2:35
  • 1
    @abc To be clear, by "implementation", Pete means the implementation of the C++ langauge. Not implementation of your functions (unless you are writing the standard library). Commented Mar 17, 2020 at 2:38
  • 2
    @eerorika Newlib is an implementation of the standard library for embedded targets. This file comes from the GNU Arm Embedded toolchain. Commented Mar 17, 2020 at 2:41
  • 1
    @abc Ah. Then it is indeed allowed, and in fact necessary to use a reserved identifier :) Commented Mar 17, 2020 at 3:08

3 Answers 3

6

1 is true, so you can use the macro in an #if test. That's not usually very useful for header guards, but it certainly doesn't hurt. For other macros which might be tested in boolean expressions, the true value is definitely useful.

Some people just like the consistency. And that's the definition that gcc chooses by default if you put -D TESTME on the command line.

However,

#define __NEWLIB_H__ 1 

is not cool unless it's in an implementation of the standard library, because names starting with two underscores (or an underscore and a capital letter) are reserved for use by the implementation, and should never be used in portable applications.

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

3 Comments

Okay, yeah someone in the comments made a similar comment, but in this case it is actually an implementation of the standard library.
Mind specifying what -DTESTME means? I couldn't find it in the ~1000 page gcc documentation or on the internet suprisingly.
@abc: it means "predefine the macro TESTME" (in this case to a default value but it's common to provide an explicit value). Used to pass configuration settings into the compilation. (gcc.gnu.org/onlinedocs/gcc-9.3.0/gcc/…)
3

When used purely as an #include guard, there is no difference between

#ifndef __NEWLIB_H__ #define __NEWLIB_H__ 

and

#ifndef __NEWLIB_H__ #define __NEWLIB_H__ 1 

However, in general, there is a distinction.

Compiler error

#ifndef ABCD #define ABCD #endif int main() { #if defined(ABCD) && (ABCD == 1) std::cout << "ABCD is 1\n"; #else std::cout << "ABCD is not 1\n"; #endif } 

Outputs the string "ABCD is 1"

#ifndef ABCD #define ABCD 1 #endif int main() { #if defined(ABCD) && (ABCD == 1) std::cout << "ABCD is 1\n"; #else std::cout << "ABCD is not 1\n"; #endif } 

Outputs the string "ABCD is not 1"

#ifndef ABCD #define ABCD 10 #endif int main() { #if defined(ABCD) && (ABCD == 1) std::cout << "ABCD is 1\n"; #else std::cout << "ABCD is not 1\n"; #endif } 

Comments

2

#define by itself will replace the symbol with nothing.

On the other hand, #define 1, as you call it, will replace the symbol with 1 everywhere it is found in the file. So, for example, the following code:

#include <iostream> #define EXAMPLE "hello" int main() { std::cout << EXAMPLE; return 0; } 

prints

hello 

This is because EXAMPLE here is replaced with "hello", making the print statement equivalent to:

std::cout << "hello"; 

If we change the #define statement to this instead:

#define EXAMPLE 

This will give a compile error:

main.cpp: In function ‘int main()’: main.cpp:15:25: error: expected primary-expression before ‘;’ token std::cout << EXAMPLE; 

As to why you would ever use this second form of #define, it's because there is another processor directive that you can use called #ifdef:

#include <iostream> #define EXAMPLE int main() { #ifdef EXAMPLE std::cout << "EXAMPLE defined."; #endif return 0; } 

This will print:

EXAMPLE defined. 

Because #ifdef (and its relative #ifndef) only require that the symbol be defined, we don't really need to give it a value. It just needs to be there to work.

A common place you see this kind of stuff is with header guards (which is probably what you're seeing). You can also see it with platform identification, or even to determine whether the compiler is using C++ or not.

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.