Preprocessor macro and BOOL weirdness - objective-c

Code below yields the output "yes defined", "no defined" and "yes". Why?
#define FOOBAR NO
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef YES
NSLog(#"yes defined");
#endif
#ifdef NO
NSLog(#"no defined");
#endif
#if FOOBAR == YES
NSLog(#"yes");
#else
NSLog(#"no");
#endif
// ...
}
YES and NO are not undefined, objc.h defines them as:
typedef signed char BOOL;
#define YES (BOOL)1
#define NO (BOOL)0

What is the value of NO? If it's undefined (like YES), they will both evaluate to 0.
This means your expression is essentially
#if 0 == 0
which is of course true, and thus causes the first call to be compiled.
UPDATE: Not sure how BOOL is defined, but casting to what might be a typedef:ed type is not a very good idea when dealing with the preprocessor. Remember that the the #if is evaluated by the preprocessor, not by the compiler. Read something like this for more information about expressions in the preprocessor. Especially:
The preprocessor does not know anything about types in the language.

All identifieres that the preprocessor doesn't know of are replaced with 0 for evaluation in #if directives. If you don't have defined YES and NO both are 0 (and thus equal).

Related

if else define for preprocessor

//initial code:
#define MYDEBUG YES
#if (defined(MYDEBUG) && MYDEBUG == YES)
#define NATIVEUNITID #"unitid_debug"
#else
#define NATIVEUNITID #"unitid_release"
#endif
//somewhere inside the code
NATIVEUNITID is #"unitid_release"
May be I do not understand something. But why? What is the proper way to define
NATIVEUNITID using the other define?
I've tried both #if (MYDEBUG) and #if (MYDEBUG == true) but I obtain the same result.
Please, help me to understand this simple case. How can I receive
NATIVEUNITID is #"unitid_debug" ?
The preprocessor cannot evaluate == for "strings".
You could retain your notation if you write #DEFINE YES 1
To improve this answer
#if !defined(YES)
#define YES (BOOL)1
#endif
#if !defined(NO)
#define NO (BOOL)0
#endif
before
#define MYDEBUG YES

Conditional compilation error in objective-c

This code isn't working due to Error that I couldn't get which is :
Expected ‘)’
type specifier missing default to ‘int’
Expected parameter declaration
conflicting types or ’NSLog'
this error only appear in line 4
please help thanks,
#import <Foundation/Foundation.h>
#define SYS
#ifdef SYS
NSLog (#"SYS is Define ");
#endif
#define minimum(x,y) (x < y ? x:y)
#define Lower_case(x) ((x>'a') && (x<'z'))
#define ToUper_case(x) ((x-'a')+'A')
#define Uper_case(x) (Lower_case(x) ? (x-'a')+'A':x)
#interface NewDef : NSObject
#end
You have a code statement:
NSLog (#"SYS is Define ");
which is not inside any method/function. This is not allowed in (Objective-)C(++).
You can probably achieve what you wish using:
#pragma message "SYS is Define "
This is a compile-time instruction, just as #define is, to the compiler to (somehow) present a message. In Xcode if this line is reached it will be marked with a warning icon:
If you comment out the #define SYS then the mark will go away as the line is no longer reached:
HTH

extern function with macro

Im having a linker problem in Objective C when i attempt to do a marco with a extern function. Any idea why?
Header file
To assist in doing comparison with the device version
extern NSString* getOperatingSystemVerisonCode();
#if TARGET_OS_IPHONE // iOS
#define DEVICE_SYSTEM_VERSION [[UIDevice currentDevice] systemVersion]
#else // Mac
#define DEVICE_SYSTEM_VERSION getOperatingSystemVerisonCode()
#endif
#define COMPARE_DEVICE_SYSTEM_VERSION(v) [DEVICE_SYSTEM_VERSION compare:v options:NSNumericSearch]
#define SYSTEM_VERSION_EQUAL_TO(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) (COMPARE_DEVICE_SYSTEM_VERSION(v) != NSOrderedDescending)
.mm file
NSString* getOperatingSystemVerisonCode()
{
/*
[[NSProcessInfo processInfo] operatingSystemVersionString]
*/
NSDictionary *systemVersionDictionary =
[NSDictionary dictionaryWithContentsOfFile:
#"/System/Library/CoreServices/SystemVersion.plist"];
NSString *systemVersion =
[systemVersionDictionary objectForKey:#"ProductVersion"];
return systemVersion;
}
Linker Error:
Undefined symbols for architecture x86_64:
"_getOperatingSystemVerisonCode", referenced from:
-[Manager isFeatureAvailable] in Manager.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The problem is not caused by the macro definition.
The getOperatingSystemVerisonCode() function is defined in a ".mm" file and therefore
compiled as Objective-C++. In particular, the function name is mangled as a C++ function.
But when referenced from (Objective-)C sources, the unmangled name is expected.
You have two options to solve the problem:
Rename the ".mm" file to ".m", so that it is compiled as an Objective-C file.
In the header file where the function is declared, add the extern "C" declaration to enforce C linkage even in an (Objective-)C++ file:
#ifdef __cplusplus
extern "C" {
#endif
NSString* getOperatingSystemVerisonCode();
#ifdef __cplusplus
}
#endif
For more information about mixing C and C++, see for example
Combining C++ and C - how does #ifdef __cplusplus work?

In Objective c how to define custom boolean type?

typedef signed char BOOL;
// BOOL is explicitly signed so #encode(BOOL) == "c" rather than "C"
// even if -funsigned-char is used.
#if __has_feature(objc_bool)
#define YES __objc_yes
#define NO __objc_no
#else
#define YES ((BOOL)1)
#define NO ((BOOL)0)
#endif
Above is how BOOL is defined in iOS. Following the same way i am trying to define another boolean with value ON OFF and did like below.
typedef signed char ONOFF;
#if __has_feature(objc_bool)
#define ON __objc_yes
#define OFF __objc_no
#else
#define ON ((ONOFF)1)
#define OFF ((ONOFF)0)
#endif
When this type defined as parameter autocompletion write it as 'int' instead of 'ONOFF'. But for BOOL type it rightly writing it as 'BOOL'.
Is that possible to create my custom boolean type that works similarly like BOOL in all aspects?
For some properties the readability will be better with ON/OFF, hence trying the above.
Any suggestions?
Edit
One quick work around to use ON/OFF in place of YES/NO is
typedef YES ON;
typedef NO OFF;
But still wondering why i cannot create my own boolean type.
Keep it simple?
typedef BOOL ONOFF;
#define ON YES
#define OFF NO

Using constant to declare an array of item

Is it possible to use some thing like this in Objective-C:
#define number_of_items 10
and then using it as:
int arr[number_of_items];
Yes, assuming you mean Objective C. It's pretty much a superset of "proper" C so this is perfectly okay. It's also okay in both C and C++.
You can see that it works in the following transcript:
pax> cat qq.m
#import <objc/Object.h>
// First method.
#define number_of_items 10
int arr[number_of_items];
// Second method.
#define NUMBER_OF_ROWS 10
#interface test : Object{ int xyzzy[NUMBER_OF_ROWS]; }
#end;
pax> vi qq.m ; gcc -o qq.o -c qq.m -lobjc
pax> # no errors occurred
And, now that we've finally seen what you're actually using:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define NUMBER_OF_ROWS_ (IS_IPAD? 18: 18)
NUMBER_OF_ROWS_ is not a constant, since it depends on the return value of the function UI_USER_INTERFACE_IDIOM().
In other words, it cannot be calculated at compile time. That's why you're getting the error. You can see this by compiling the following code:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define NUMBER_OF_ROWS_ (IS_IPAD ? 18: 20)
int UI_USER_INTERFACE_IDIOM(void) {return 20;}
int UIUserInterfaceIdiomPad;
int main (void) {
int arr[NUMBER_OF_ROWS_];
return 0;
}
Under gcc --pedantic, you get:
qq.m: In function ‘main’:
qq.m:8: warning: ISO C90 forbids variable length array ‘arr’
You either need to use a dynamically adjustable collection like NSMutableArray or use an array of the maximum size desired and only use what you need of that.