What is the purpose of using #define to define a constant with no value? - preprocessor

What is the purpose of using #define to define a constant with no value?
Such as:
#define TOKEN

You can use it to enable or disable certain code using #ifdef or #ifndef, eg this:
#ifdef TOKEN
printf("token is defined");
#endif
One use for this would be to toggle logging in debug builds. Another would be include guards.

As #Nutomic says, this sort of #define is useful for enabling/disabling certain bits of code. I've seen this used to create compile-time options for a given library:
#ifdef STRICT_PARSING
//...
#endif
#ifdef APPROXIMATE_PARSING
//...
#endif
#ifdef UNICODE //this is especially useful when trying to control Unicode vs ANSI builds
//call Unicode functions here
#else
//call Ansi functions here
#endif
#ifdef USE_STL //another good one, used to activate or deactivate STL-based bits of an API; the function declarations were dependent on USE_STL being defined. A plain-C API was exposed either way, but the STL support was nice too.
std::string MyApi();
#endif

Related

Adopting os_log APIs while keeping backward compatibility

I'm trying to add support for the new logging and activity tracing APIs to a library in a way that maintains backward compatibility for users of the library who haven't yet adopted the latest version of the OS (iOS or macOS). I'm defining custom logging macros for each level of logging, and then for older OSes, falling back to NSLog. I've gotten this working, with one problem.
The new APIs require you to mark any non-constant, non-scalar values as explicitly public if you want them to show up in log output. This is what an invocation of my macro looks like:
UZKLogInfo("Reading file %{public}# from archive", fileName);
This compiles fine with the SDK that includes os_log (e.g. iOS 10.0 or later), but when I compile with an earlier version so my macro falls back to NSLog, I get a compiler warning:
Using 'public' format specifier annotation outside of os_log()/os_trace()
And the log line printed looks like this:
Reading file <decode: missing data> from archive
This is a simplified version of my macro definition (only including the info definition and simplifying the conditional:
#if UNIFIED_LOGGING_SUPPORTED
#import os.log;
#define UZKLogInfo(format, ...) os_log_info(OS_LOG_DEFAULT, format, ##__VA_ARGS__);
#else // Fall back to regular NSLog
#define UZKLogInfo(format, ...) NSLog(#format, ##__VA_ARGS__);
#endif
Is there any way to strip the "{public}" text (some kind of string replacement?) from format in the fallback case? Or is there another way to support the old and new APIs without giving up the level of info I've always shown in the logs? I need to use a macro (according the last year's WWDC session on the topic, or else I lose the call site metadata.
I chose to do an NSString replace in the macro, and to suppress the compiler warnings as part of it, so it could be done for each line, rather than globally for the whole file or project. It looks like this:
#if UNIFIED_LOGGING_SUPPORTED
#import os.log;
#define UZKLogInfo(format, ...) os_log_info(OS_LOG_DEFAULT, format, ##__VA_ARGS__);
#else // Fall back to regular NSLog
#define _removeLogFormatTokens(format) [#format stringByReplacingOccurrencesOfString:#"{public}" withString:#""]
#define _stringify(a) #a
#define _nsLogWithoutWarnings(format, ...) \
_Pragma( _stringify( clang diagnostic push ) ) \
_Pragma( _stringify( clang diagnostic ignored "-Wformat-nonliteral" ) ) \
_Pragma( _stringify( clang diagnostic ignored "-Wformat-security" ) ) \
NSLog(_removeLogFormatTokens(format), ##__VA_ARGS__); \
_Pragma( _stringify( clang diagnostic pop ) )
#define UZKLogInfo(format, ...) _nsLogWithoutWarnings(format, ##__VA_ARGS__);
#endif
It's called like so:
UZKLogInfo("Message: %#", anObjectToLog);

#define a global preprocessor directive in a separate file in Objective-C

I want to define a global preprocessor directive in my app. For example:
In MyProgram.h, I define:
#define USE_LOCALHOST
I import this file from beginning in appDelegate.m.
For the later use, in another file, I refer to this global preprocessor directive.
In MyWebService.h, I define:
#ifdef USE_LOCALHOST
static NSString *MY_SERVER = #"http://192.168.1.130:8888";
#else
static NSString *MY_SERVER = #"http://myserver.com";
#endif
However, the value of MY_SERVER is always #"http://myserver.com". How to make it work properly? Thanks.
Define it in .pch. And you will never forget to include .h-file where you have defined USE_LOCALHOST.
Or you can define it in build settings in Preprocessor Macros.
For example only for Debug.
#define works only in the file where it's defined in. But you can #import "MyProgram.h" in MyWebService.h and problem solved. Every time you need to access USE_LOCALHOST, just import the header file.

XCode: Check destination platform with define

Do exist some standard defines, that specify destination platform, e.g. DEST_IOS or DEST_OSX? Or must I add its in project's settings?
I need this for using same library on Mac and iPad.
Yes. Include TargetConditionals.h, and I use the following to make them a bit easier to use:
#import <TargetConditionals.h>
#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
#define TARGET_OSX 1
#else
#define TARGET_IOS 1
#endif
(this is in a common project header file).
And then to use the macros:
#if TARGET_OSX
// OSX-specific thing here
#else
// iOS-specific thing here
#endif

Operator 'defined' requires an identifier ios

I've below code in my project dlog should print the values in console if isConsoleLogActive is YES.
It gives error like Operator 'defined' requires an identifier
#if defined ([Util isConsoleLogActive])// Operator 'defined' requires an identifier in this line
#define DLog(...) NSLog(__VA_ARGS__)
#define DTrace() NSLog(#"%s", __PRETTY_FUNCTION__)
#else
#define DLog(...) /* */
#define DTrace() /* */
#endif
if I use the same code([Util isConsoleLogActive]) in my .m it works perfectly fine. I face this issue only in #define
What could be the issue. Please give me some idea.
The various commands that start with # are preprocessor directives. These get executed before the compilation phase at build time, before your application actually executes. You should use the preprocessor directives to conditionally include different code in your application based on build configuration. The preprocessor, however, is the wrong way to handle conditional execution on a specific platform at runtime; for that, you want your standard "if...else" logic.
If your goal with that statement is to determine if the given selector exists, try respondsToSelector, instead.
Result of
[Util isConsoleLogActive]
is not known at compile-time. So you can not use it with '#if defined'.

Detect compilation on Bada OS

I would like to do something similar to #ifdef __linux__, but with the bada SDK. Is there a constant defined by default?
Also, can I detect when I am compiling for the simulator?
You can, by checking the MingW Compiler's keyword, here's an interesting link that would point you in the right spot... so in theory you could have it this way
#ifdef __MINGW32__
/* we're in the simulator target */
#else
/* we're in the native target */
#endif
I use something like :
#ifdef SHP
# define CONFIG_SUPPORT_API_Osp 1 // bada
#endif
I wish there is also a define that tell sdk version or target api too ..
Use :
#ifdef _DEBUG
// Your code
#endif

Resources