If I add a macro "FOO=bar" under GCC_PREPROCESSOR_DEFINITIONS (or Preprocessor Macros if you use XCode"), what would be the best way to access the value of "FOO"?
Currently, I use the clumsy:
#define MACRO_NAME(f) #f
#define MACRO_VALUE(f) MACRO_NAME(f)
#ifdef FOO
NSLog(#"%s", MACRO_VALUE(FOO));
#else
NSLog(#"undefined");
#endif
This will output "bar"
Surely, there must be a better/cleaner way?
What you are doing is the way to stringize (or stringify) macro values. The indirection is unavoidable.
This is mentioned in the GCC preprocessor manual section (archived link) that Rob linked to:
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
==> "foo"
xstr (foo)
==> xstr (4)
==> str (4)
==> "4
NSLog(#"%s", #FOO);
See Stringification. It's the technique you're already using. What was wrong with it?
Related
I am trying to define the value of a macro based on some condition like
#define DEV NO
#if DEV == YES
#define API_ENDPOINT_HOST #"https://my-dev.com/"
#else
#define API_ENDPOINT_HOST #"http://my-qa.com/"
#endif
But even though I have defined DEV as No, it is always taking API_ENDPOINT_HOST as #"https://my-dev.com/". What is wrong here?
Even Uli's answer is correct (as everyone expected), I want to explain it in more detail:
In PP phase an undefined identifier in an #if directive is replaced with 0. NO and YES are not defined anymore as macro as it has been in the past, but became literals. So they are undefined in PP phase.
Your second line is:
#if DEV == YES
DEV is replaced with NO …,
#if NO == YES
… what is undefined as YES is. Therefore both are replaced by 0:
#if 0 == 0
That's obviously true.
NO and YES are Objective-C constructs. The preprocessor runs before the Objective-C compiler, so does not know YES or NO yet. Usually people use 0 and 1 in preprocessor defines.
Alternatively, just define your symbol and then use #ifdef instead of #if.
#define DEV
#ifdef DEV
#define API_ENDPOINT_HOST #"https://my-dev.com/"
#else
#define API_ENDPOINT_HOST #"http://my-qa.com/"
#endif
Suppose I have two libraries ABC, XYZ and two variables ABC_FOUND XYZ_FOUND in CMakeLists.txt. In a config.h.in file, I have the following lines
#define __USE_ABC__ #ABC_FOUND#
#define __USE_XYZ__ #XYZ_FOUND#
If I do configure_file(config.h.in config.h), the output config.h file will be changed to
#define __USE_ABC__ ON
#define __USE_XYZ__ OFF
My question is how can I convert the ON/OFF options into 1/0, in other word, my desired output config.h should be
#define __USE_ABC__ 1
#define __USE_XYZ__ 0
Define ABC_FOUND to either 0 or 1 with
#cmakedefine01 #ABC_FOUND#
Use an intermediate variable in either environment to change it to USE_ABC.
Likely, you should use #cmakedefine instead of hard defines (see examples e.g. here)
But please remember that in the case of #cmakedefine you get a configuration header where "enabled features" (in terms of CMake if() command) are #define-d to a supplied value, while "disabled features" are #undef-ined. So you should test them not with #if <something> but rather with #ifdef <something>.
Hi was reviewing some Objective-C code and found out the following statement:
OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
What does this mean?
Also, what is supposed to be the syntax of this statement?
Thanks in advance.
OBJC_EXTERN is defined in <objc/objc-api.h> as
#if !defined(OBJC_EXTERN)
# if defined(__cplusplus)
# define OBJC_EXTERN extern "C"
# else
# define OBJC_EXTERN extern
# endif
#endif
and therefore prevents "C++ name mangling" even if the above declaration is
included from a C++ source file, as for example explained here:
In C++ source, what is the effect of extern "C"?
For pure C code, you can just remove the OBJC_EXTERN, because the extern
keyword is not needed in a function declaration.
NS_FORMAT_FUNCTION is defined as
#define NS_FORMAT_FUNCTION(F,A) __attribute__((format(__NSString__, F, A)))
and __attribute__((format(...))) is a GCC specific extension, also understood
by Clang:
http://clang.llvm.org/docs/LanguageExtensions.html#format-string-checking
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
It allows the compiler to check the number and types of the variable argument list
against the format string. For example
CLSLog(#"%s", 123);
would cause a compiler warning, because %s is the placeholder for a string,
but 123 is an integer.
I have this Objective-C istruction:
NSRange range = NSMakeRange(i, MIN(a, b));
where a and bare NSUIntegers.
MIN() is the macro defined in the standard NSObjCRuntime.hheader file as:
#if !defined(MIN)
#define MIN(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
#endif
During the compilation, the LLVM Compiler 4.1 highlights my instruction showing the warning: "Use of GNU statement expression extension".
What does this mean? Is it my fault? If yes, how can I fix it? If not, how can I remove the compiler warning?
It’s a late answer, I know, but you can avoid this message by adding -Wno-gnu to your compiler flags.
(In Xcode 5 I believe you can change this by going to your project’s Build Settings and adding -Wno-gnu to the “Other C Flags”, which are in the “Apple LLVM 5.0 – Custom Compiler Flags” section.)
"Statement expressions" is an extension of the GNU C compiler and allows you to execute a group of statements, returning the value of the last statement:
x = ({
statement1;
statement2;
statement3;
});
In the above example, x will have the value returned by statement3.
It is a convenient feature that enables you to have multi-statement macros that can be nested easily into other expressions. It is not, however, defined by any C standard.
Don't use -Wno-gnu, that shuts down too many warnings. Instead, use:
-Wno-gnu-statement-expression
Statement expressions have been declared.
You can selectively ignore the warning by using pragma codes without changing project settings.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wgnu"
NSRange range = NSMakeRange(i, MIN(a, b));
#pragma GCC diagnostic pop
I have tested a bit of assembler on Linux using the AT&T syntax. One thing that struck me was that the book I was reading was written from a 32-bit standpoint. Thus, all sizes would have to be changed to the correct 64-bit versions for me. Or I could (which I did) assemble the code using the --32 flag for as and the -melf_i386 flag for ld when linking. I have also adapted some of the code and to run on Windows under Cygwin.
But that got me thinking. Is there a way to do ifdef like checks in assembler to do one thing if I'm on Windows and another under Linux and also handle 32 vs 64 bit that way? For example to have a .globl _start under Linux and a .globl _main under Windows.
Or is this handled by checking before assembling and having different source files to assemble based on the result of the checks?
I.e. foo_linux.s and foo_windows.s
If so, how do you overcome that fact that you will not know which .s files you will use, and thus have to include, when you are creating your program?
For example, say that we have a socket_linux.s and a socket_windows.s. They both present an identical interface but do the OS specific work associated to sockets. But when I work with the sockets in my program I will not know if I need the Windows or Linux version included. So I would be kinda screwed :)
So how is this handled in Assembler? In C++ for example I could include my socket.h and socket.cpp and wrap all the Linux and Windows specific code in #ifdef statements.
If you use GCC to compile your files and name them .S (with uppercase S) or .sx, it will pass them through the preprocessor before invoking the assembler.
From the docs:
file.s
Assembler code.
file.S
file.sx
Assembler code which must be preprocessed.
You can add -v to the command line to see how the various sub-processes are invoked.
in MASM (.asm), you can use ifdef, ifndef and the likes, as:
ifdef X64
endif
When writing for different platforms you can define some macro for loading target specific files:
FILE target.h
#if defined(__arm__)
#define target "arm"
#elif defined(__x86_64__)
#if defined(_WIN64)
#define target "win64"
#else
#define target "linux64" // all non-Win share the same calling convention
#endif
#else
// 32bit defs
#endif
Then you can include target specific files with the macro, two string literals successively get one single literal:
#include "target.h"
#include "target_specific_code_" target ".h"
It includes one of these files:
target_specific_code_arm.h
target_specific_code_win64.h
target_specific_code_linux64.h
...
EDIT:
Like this, you can also define target specific assembler instructions for later use in inline assembly:
#ifdef ...
#define ASM_PP_LOAD_WORD "movi "
#else
#define ASM_PP_LOAD_WORD "mov "
#endif
or as macro
#ifdef ...
// when using intel assembler there is a different
// order of parameters
#define ASM_PP_LOAD_WORD(a, b) "movi " #b ", " #a
#else
#define ASM_PP_LOAD_WORD(a, b) "mov " #a ", " #b
#endif