ObjC Macros -- can I include check to see if a variable is defined within the current scope? [duplicate] - objective-c

This question already has answers here:
Conditional macro expansion
(3 answers)
Closed 8 years ago.
This isn't the macro that I'm trying to create, but this analogy of attempting to create a custom logging function that works in Obj-C and C contexts illustrates the point:
#define Log(_s, ...) do { \
/* obviously this won't work as written, */\
/* but it's what i'm trying to accomplish: */\
#if (self && _cmd) /* \
LogObjectiveC(_s, ##__VA_ARGS__); \
#else \
LogC(_s, ##__VA_ARGS__); \
#endif \
} while (0)
In this example, we're trying to consolidate two macros that are used depending on where they are defined. (LogObjectiveC is used when inside an Obj-C method, and LogC is used when inside a C function.
Is it possible check for the existence of the 'hidden' arguments (self and _cmd) inside the Macro definition?

This isn't possible, because methods, functions and parameters don't exist at macro expansion time. Macros are expanded by the preprocessor before the compiler does anything with your code.
The closest thing I can think of would be to inspect __func__ at runtime and see whether it starts with "+[" or "-[", since all Objective-C methods start with one of those and no legal C or C++ function can.

I'm marking Chuck's as the correct answer, thanks for answering.
After another 15 minutes of googling, I stumbled on this duplicate question: Conditional macro expansion (which actually goes along the lines of #Chuck's suggestions)

Related

Objective-C macro in preprocessor IF

I have a project with some macros that are defined using Objective-C statements, like this:
#define TEST [someObject someNumber] == 500
I need to define another value based on this result, like this:
#if TEST
#define THING = 1
#else
#define THING = 2
#endif
But, this doesn't work. And I can't use #ifdef TEST because the value is always defined. Even if it's false, it's still defined.
TEST is based on an ObjC statement, and it seems like the preprocessor has no way of evaluating it. So, is there no way to test for this?
In the comments you wrote:
Since TEST must be evaluated during runtime, there's no way to know the value of it during build time. Because the preprocessor can't know the value, it can't test it. Is this correct?
Yes.
The preprocessor runs (at least logically) before the rest of the compiler. It is essentially language and syntax agnostic, and does not even have access to constants defined in your code. The conditional constructs operate solely with preprocessor tokens.

How to access a constant using a String holding its name

I have a .h file that defines a few hundred constants. Let's assume this to be one of them:
#define KDSomeItem 1
I know that the Objective-C runtime API can be used to retrieve a list of instance variable names: like detailed in this question: How do I list all fields of an object in Objective-C?
I also know that the getter [object valueForKey:theName] can be used to access the ivars as found in an earlier question of mine: How to access a property/variable using a String holding its name
My question is can something simmilar be done with constants? That is can I:
a) get a list of all constants programmatically
b) access a constant if I have a string holding its name
e.g. if I had a String like this NSString * theName = #"KDSomeItem"; could I evaluate my constant using this string?
You would not be able to do this: unlike instance variables, #define-d constants do not leave a trace after the preprocessor is done with them. They leave no metadata behind - all instances of KDSomeItem in the body of your program will be replaced with 1 even before the Objective C compiler proper gets to analyze your code.
If you need the constant names to be available at run time, you would need to build all the necessary metadata yourself. In order to do that, you may want to look into "stringizing" operator of the preprocessor:
#define STR(X) #X
This macro can be applied to a preprocessor constant, and produce a C string literal with its name:
const char *nameOfKDSomeItem = STR(KDSomeItem); // same as "KDSomeItem"
Nope. Your constant is a preprocessor macro. It is textually substituted into your source code where you use it.

#define vs const in Objective-C

I'm new to Objective-C, and I have a few questions regarding const and the preprocessing directive #define.
First, I found that it's not possible to define the type of the constant using #define. Why is that?
Second, are there any advantages to use one of them over the another one?
Finally, which way is more efficient and/or more secure?
First, I found that its not possible to define the type of the constant using #define, why is that?
Why is what? It's not true:
#define MY_INT_CONSTANT ((int) 12345)
Second, are there any advantages to use one of them over the another one?
Yes. #define defines a macro which is replaced even before compilation starts. const merely modifies a variable so that the compiler will flag an error if you try to change it. There are contexts in which you can use a #define but you can't use a const (although I'm struggling to find one using the latest clang). In theory, a const takes up space in the executable and requires a reference to memory, but in practice this is insignificant and may be optimised away by the compiler.
consts are much more compiler and debugger friendly than #defines. In most cases, this is the overriding point you should consider when making a decision on which one to use.
Just thought of a context in which you can use #define but not const. If you have a constant that you want to use in lots of .c files, with a #define you just stick it in a header. With a const you have to have a definition in a C file and
// in a C file
const int MY_INT_CONST = 12345;
// in a header
extern const int MY_INT_CONST;
in a header. MY_INT_CONST can't be used as the size of a static or global scope array in any C file except the one it is defined in.
However, for integer constants you can use an enum. In fact that is what Apple does almost invariably. This has all the advantages of both #defines and consts but only works for integer constants.
// In a header
enum
{
MY_INT_CONST = 12345,
};
Finally, which way is more efficient and/or more secure?
#define is more efficient in theory although, as I said, modern compilers probably ensure there is little difference. #define is more secure in that it is always a compiler error to try to assign to it
#define FOO 5
// ....
FOO = 6; // Always a syntax error
consts can be tricked into being assigned to although the compiler might issue warnings:
const int FOO = 5;
// ...
(int) FOO = 6; // Can make this compile
Depending on the platform, the assignment might still fail at run time if the constant is placed in a read only segment and it's officially undefined behaviour according to the C standard.
Personally, for integer constants, I always use enums for constants of other types, I use const unless I have a very good reason not to.
From a C coder:
A const is simply a variable whose content cannot be changed.
#define name value, however, is a preprocessor command that replaces all instances of the name with value.
For instance, if you #define defTest 5, all instances of defTest in your code will be replaced with 5 when you compile.
It is important to understand the difference between the #define and the const instructions which are not meant to the same things.
const
const is used to generate an object from the asked type that will be, once initialised, constant. It means that it is an object in the program memory and can be used as readonly.
The object is generated every time the program is launched.
#define
#define is used in order to ease the code readability and future modifications. When using a define, you only mask a value behind a name. Hence when working with a rectangle you can define width and height with corresponding values. Then in the code, it will be easier to read since instead of numbers there will be names.
If later you decide to change the value for the width you would only have to change it in the define instead of a boring and dangerous find/replace in your whole file.
When compiling, the preprocessor will replace all the defined name by the values in the code. Hence, there is no time lost using them.
In addition to other peoples comments, errors using #define are notoriously difficult to debug as the pre-processor gets hold of them before the compiler.
Since pre-processor directives are frowned upon, I suggest using a const. You can't specify a type with a pre-processor because a pre-processor directive is resolved before compilation. Well, you can, but something like:
#define DEFINE_INT(name,value) const int name = value;
and use it as
DEFINE_INT(x,42)
which would be seen by the compiler as
const int x = 42;
First, I found that its not possible to define the type of the constant using #define, why is that?
You can, see my first snippet.
Second, are there any advantages to use one of them over the another one?
Generally having a const instead of a pre-processor directive helps with debugging, not as much in this case (but still does).
Finally, which way is more efficient and/or more secure?
Both are as efficient. I'd say the macro can potentially be more secure as it can't be changed during run-time, whereas a variable could.
I have used #define before to help create more methods out of one method like if I have something like.
// This method takes up to 4 numbers, we don't care what the method does with these numbers.
void doSomeCalculationWithMultipleNumbers:(NSNumber *)num1 Number2:(NSNumber *)num2 Number3:(NSNumber *)num23 Number3:(NSNumber *)num3;
But I also what to have a method that only takes 3 numbers and 2 numbers so instead of writing two new methods I am going to use the same one using the #define, like so.
#define doCalculationWithFourNumbers(num1, num2, num3, num4) \
doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), (num4))
#define doCalculationWithThreeNumbers(num1, num2, num3) \
doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), nil)
#define doCalculationWithTwoNumbers(num1, num2) \
doSomeCalculationWithMultipleNumbers((num1), (num2), nil, nil)
I think this is a pretty cool thing to have, I know you can go straight to the method and just put nil in the spaces you don't want but if you are building a library it is very useful. Also this is how
NSLocalizedString(<#key#>, <#comment#>)
NSLocalizedStringFromTable(<#key#>, <#tbl#>, <#comment#>)
NSLocalizedStringFromTableInBundle(<#key#>, <#tbl#>, <#bundle#>, <#comment#>)
are done.
Whereas I don't believe you can do this with constants. But constants do have there benefits over #define like you can't specify a type with a #define because it is a pre-processor directive that is resolved before compilation, and if you get an error with #define they are harder to debug then constants. Both have there benefits and downsides but I would say it all depends on the programmer to which one you decided to use. I have written a library with both them in using the #define to do what I have shown and constants for declaring constant variables which I need to specify a type on.

Pre-compile expandable macro

I'm trying to save some time / make my code readable. I have a lot of 'isXXX' messages that return BOOL. I am constantly adding more 'is' messages. Is it possible to make a macro that's expandable at pre-compile time via a list.
I want to specify:
isMacro(1, 2, 3).
And for each of those, I want the macro to expand it into a full -(BOOL)is1 {...}, -(BOOL)is2...
It seems like this would be a good use of the precompiler macro expansion, but I'm not sure how to implement the isMacro(...) part. (Specifically, the ... that expands into full functions before compile).
--- Update:
The 'is' methods are all dynamically computed, but they are all common.
I'm testing a single variable against an enum value and determining whether it's equal. I can't #synthesize them, because it's dynamic. I have all of them in a #property for convenience. I just want something that's like #synthesize, where I can list all of them, and create a dynamic response for each isXXX method.
Also, I don't want to run isCheck:(opMode)mode, since there is no pre-compile checking to make sure it's a valid enum value.
All of the is functions are in the following format:
-(BOOL) isTurtle { return operationMode == Turtle; } The key is that I want it to function as a property for simplicity. Therefore, I don't want something like is:(opMode)mode, where I have to specify BOOL res = [obj is:Tutle];
If you could use Boost.Preprocessor, the BOOST_PP_REPEAT_FROM_TO macro should suit your need.
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#define IS_METHODS(depth, n, aux) -(BOOL)is ## n { return aux == n; }
#implementation Foo
BOOST_PP_REPEAT_FROM_TO(1, 31, IS_METHODS, operationMode)
#end
If you can't, you're out of luck. Implementing BOOST_PP_REPEAT_FROM_TO is about the same effort as just writing the 30+ functions directly.
Also I don't see how [obj isMode:12] is really worse than obj.is12. The former also allows a variable mode, and is less cryptic to other programmers (think about the maintenance effort).

Is there a difference between an "function" and an "macro" in Objective-C?

I am wondering if both are the same thing?
They are not the same thing. A function in C or Objective-C is the organization of some procedural code into a single unit. It has very specific semantics and you can read about them in any basic C book with much more advanced information in more advanced books.
On the other hand, a macro is created during the pre-processing phase of compilation and is not a separate part of the actual binary. With a macro, the macro is actually replaced in code before complication happens so that copies are injected wherever the macro is used. That's why side effects are important to consider when using macros (because if the macro uses the same argument more than once, the side effects will occur more than once).
Here is a quick example to illustrate a macro:
#define SHOW_STRING_TWICE(string) printf("%s\n%s\n", string, string)
// ...
SHOW_STRING_TWICE("Hello, macro!");
During the pre-processing, the macro is expanded to this code:
printf("%s\n%s\n", "Hello, macro!", "Hello, macro!");
You can see how side effects are an issue in this code:
#define DOUBLE_NUMBER(number) ((number) + (number))
// ...
int doubleRandom = DOUBLE_NUMBER(generate_random_number());
In this case, when the macro is expanded, generate_random_number() is actually called twice when you would have expected it to be called only once.