This question already has answers here:
Macro compiler error: "Parse Issue" when an argument name appears elsewhere
(2 answers)
Closed 9 years ago.
The following macro is giving me a parse error. Can't see what's wrong here.
#define adjust(tag, x, y) if (self.tag==tag) { origin.x += x; origin.y += y; return origin; }
....
adjust(20, 28, 265)
EDIT:
Look at the attached screenshot. I want to use macro expansion just to improve the code readability. It's a very local usage, hence no risk or reuse etc.
Your macro refers to an undefined attribute origin, which if it doesn't exist in the scope of the replacement, will cause a compiler error after the macro has been expanded. Actually, as a whole, your macro isn't very modular. For example, you have references to tag and self, which are attributes that
Would be very contextual
Would cause compilation to fail if they do not occur and have specific meaning after macro expansion has been completed
Related
Let's review Clang's MIN macro through this article: Deep learning IOS development of macro. The final result is what you can also find here:
#define __NSX_PASTE__(A,B) A##B
#define __NSMIN_IMPL__(A,B,L) ({\
__typeof__(A) __NSX_PASTE__(__a,L) = (A);\
__typeof__(B) __NSX_PASTE__(__b,L) = (B);\
(__NSX_PASTE__(__a,L) < __NSX_PASTE__(__b,L)) ? __NSX_PASTE__(__a,L) : __NSX_PASTE__(__b,L);\
})
But I don't understand the need of defining __NSX_PASTE__. Wouldn't it be the same and more readable to use directly:
#define __NSMIN_IMPL__(A,B,L) ({\
__typeof__(A) __a##L = (A);\
__typeof__(B) __b##L = (B);\
(__a##L < __b##L) ? __a##L : __b##L;\
})
The simple answer is the __NSX_PASTE__ is required as without it the __COUNTER__ macro (not shown in the question but see the full source in the linked article, or look at the definition in Apple's NSObjCRuntime.h) will not be expanded. This is due to the weird and wonderful way the C Preprocessor works and how it handles stringification and concatenation, a good place to read how all this works is the GCC documentation on macros.
To see the results with and without the __NSX_PASTE__ put your above macros in a test file, say test.m, in Xcode renaming __NSMIN_IMPL__ to MY__NSMIN_IMPL__ (or you'll get a duplicate macro warning), add the macro you omitted - again renamed to avoid clashes:
#define MY_MIN(A,B) MY__NSMIN_IMPL__(A,B,__COUNTER__)
and add some code which uses MY_MIN. Now in Xcode select the menu item Product > Perform Action -> Preprocess "test.m" - this will show you the result after the preprocessor has run. If you try it with your version of __NSMIN_IMPL__ which does not use __NSX_PASTE__ you will see __COUNTER__ is not expanded.
HTH
Is there a way in VBA to create classes and/or methods that have a limited list of acceptable constants to use as arguments or in assignment statements?
These exist already in VBA per the images below:
I would like to incorporate this in my classes.
It's not a limited set of constants. You type xlsheethidden the program sees 0. The compiler puts 0 into the program. Nothing stops you doing this. ReportCS1.Visible = 1,000,000. It's an aid to writing programs, it doesn't form part of the finished program.
If you want to limit what can be passed then you'll need to write code checking what was passed, if wrong do err.raise(&h80070000 OR 13, blah,blah, blah).
This turns a WinError into a HResult - 13 seems resonable. = 0x8007000d
//
// MessageId: ERROR_INVALID_DATA
//
// MessageText:
//
// The data is invalid.
//
#define ERROR_INVALID_DATA 13L
Tim Williams answered my question in his comment. Thanks Tim!
You can create an Enum See: cpearson.com/excel/Enums.aspx
I am new to iOS development and I just want to know the meaning of macro in Objective-C?
I have found that "macro" is used with #define but still do not get its meaning.
http://www.saturngod.net/ios-macro-define-value-with-condition
Yes, Larme is right. Macros can be used in many languages, it's not a specialty of objective-c language.
Macros are preprocessor definitions. What this means is that before your code is compiled, the preprocessor scans your code and, amongst other things, substitutes the definition of your macro wherever it sees the name of your macro. It doesn’t do anything more clever than that.
Almost literal code substitution. e.g.-
Suppose you want a method to return the maximum of two numbers. You write a macro to do this simple task:
#define MAX(x, y) x > y ? x : y
Simple, right? You then use the macro in your code like this:
int a = 1, b = 2;
int result = 3 + MAX(a, b);
EDIT:
The problem is that the preprocessor substitutes the macro definition into the code before compilation, so this is the code the compiler sees:
int a = 1, b = 2;
int result = 3 + a > b ? a : b;
C order of operations requires the sum 3 + a be calculated before the ternary operator is applied. You intended to save the value of 3 + 2 in result, but instead you add 3 + 1 first, and test if the sum is greater than 2, which it is. Thus result equals 2, rather than the 5 you expected.
So you fix the problem by adding some parentheses and try again:
#define MAX(x, y) ((x) > (y) ? (x) : (y))
A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls.
An object-like macro is a simple identifier which will be replaced by a code fragment. It is called object-like because it looks like a data object in code that uses it. They are most commonly used to give symbolic names to numeric constants.
You create macros with the ‘#define’ directive. ‘#define’ is followed by the name of the macro and then the token sequence it should be an abbreviation for, which is variously referred to as the macro's body, expansion or replacement list. For example,
#define BUFFER_SIZE 1024
defines a macro named BUFFER_SIZE as an abbreviation for the token 1024. If somewhere after this ‘#define’ directive there comes a Objective C statement of the form
foo = (char *) malloc (BUFFER_SIZE);
The Objective C compiler will see the same tokens as it would if you had written
foo = (char *) malloc (1024);
You can also define macros whose use looks like a function call. These are called function-like macros. To define a function-like macro, you use the same ‘#define’ directive, but you put a pair of parentheses immediately after the macro name.
Like:
#define isIphone([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
#define GetImage(imageName) [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:imageName ofType:#"png"]]
Macros are compile time constants. That means they will replaced with actual values in the compile time.
#define MIN_VALUE 3 // Definition
if(x > MIN_VALUE) // Usage
{
}
While compiling it actually looks like
if(x > 3) // During compilation
{
}
Wikipedia has the answer, under Macro.
Definition:
The term originated with macro-assemblers, where the idea is to make available to the programmer a sequence of computing instructions as a single program statement, making the programming task less tedious and less error-prone.
Usage:
Keyboard and mouse macros that are created using an application's built-in macro features are sometimes called application macros. They are created by carrying out the sequence once and letting the application record the actions. An underlying macro programming language, most commonly a Scripting language, with direct access to the features of the application may also exist.
Here is the situation. I am using MS Visual Sturio 2005 and Excel 2007. I create a dll containing a function
extern "C" VARIANT WINAPI MyFunc()
{
VARIANT res;
memset(&res, 0, sizeof(VARIANT));
::VariantInit(&res);
return res;
}
That is called from Excel VBA. This function seems to work correctly.
But there is a problem: when VBA returns from my function and tries to execute the next floating point instruction I see a window:
runtime error 6. Overflow.
This error is pretty strange. I have been investigating it the last couple of days, here are the "facts" I have collected:
1) The error shows up only after the first call to the dll. All successive calls to this function don't cause this error.
2) The error is triggered by the first (seemingly harmless) floating-point instruction in the VBA code after the control returns from the dll:
Dim dMinValue As Double
dMinValue = 10000000#
3) The project from which the dll is built contains 4 files: mydll.cpp, mydll.def, cSomeClass.cpp and cSomeClass.h.
cSomeClass is a fairly complicated class that calls code from my other libs. BUT mydll.cpp does not use cSomeClass in any way. Here is the code of mydll.cpp:
#include <OAIdl.h>
#include <float.h>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
extern "C" VARIANT WINAPI MyFunc()
{
unsigned int u;
u = _controlfp(0, 0);
_controlfp(u & ~(_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT), _MCW_EM);
VARIANT res;
memset(&res, 0, sizeof(VARIANT));
::VariantInit(&res);
return res;
}
The initial version of MyFunc() didn't have the first 3 lines (the ones messing with _controlfp()), it was causing "Runtime Error 6, Overflow" in VBA. Then I started suspecting that this error could be related to the FPU registeres (I know very little about those). When I added these 3 lines an exception was thrown when I call _controlfp() - "0xC0000090: Floating-point invalid operation.". If I leave the code as it is presented above the exception causes stack unwind (we don't get to the VARIANT res; line) and a window saying "runtime error 6. Overflow." is displayed in Excel. To sum it up, adding these 3 lines caused the floating point exception to be thrown earlier. If we catch the exception thrown in the 3rd line (with an __except clause) and ignore it (by callng _clearfp()) then no errors are reported in Excel.
A NASTY DETAIL: if I remove the files cSomeClass.cpp and cSomeClass.h from the Visual Studio project the error is not reproduced. cSomeClass.h is not includeed into mydll.cpp, but if I remove cSomeClass.* files from the project the dll size is significantly reduced.
My best guess at this point is that there are some static objects in the LIB-s referenced by cSineClass.cpp that cause this. Maybe these objects are initialized (constructed) when the dll is being loaded (according to my experiments, before to DllMain) and this somehow causes an error flag for "0xC0000090: Floating-point invalid operation." being set. When we return to Visual Basic from the dll, somethis calls _controlfp and enables the floating-point exceptions (they are turned off in С++) when raises "0xC0000090: Floating-point invalid operation." that somehow gets converted to "Runtime Error 6. Overflow." that I see in Excel. This is just a guess. Up unti now I haven't found any static objects that could be doing this.
Unfortunately I haven't been able to create a small example reproducing this error, because it shows up only when I have cSomeFile.* as part of the project. And those files require all of my libs...
If anyone knows what could be the cause of such behaviour or have suggestions about how to advance with my investigations that would be greatly appreciated.
So I have at various points had similar random issues with Excel, and you are my hero.
I found that by calling _clearfp(), it will quiet the error and return the value properly. I think the issue arises from the fact that I use _HUGE values all over the place to signify invalid floats. Which sets the flag, and causes Excel (and only excel) to barf. I've never run into any issues with runtime exceptions before in any other program.
1) Apparently, when I get into the DLL code from VBA the FPU exceptions are turned off, like if someone called
u = _controlfp( 0, 0 );
_controlfp( u & ((_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT )), _MCW_EM );
before passing control to my dll code.
2) Calling std::numeric_limits::signaling_NaN() at any point causes the _EM_INVALID flag to be set in the floating point status word (can be seen by calling _statusfp()).
3) When the control is returned from the DLL the FPU exceptions seem to be turned on. As if someone called:
u = _controlfp( 0, 0 );
_controlfp( u & (~(_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | EM_UNDERFLOW | _EM_INEXACT )), _MCW_EM );
This causes a runtime error.
# include <stdio.h>
# define ONE 1
# define TWO 2
# define ONE TWO
# define TWO ONE
int main ( void )
{
printf("ONE = %d, TWO = %d\n", ONE, TWO );
return 0;
}
what actually happens when we write this way? In the 4th line #define ONE TWO, does the pre processor replace it blindly as 1 2 immediately?
If you are using xcode 3 you could do a right click on the file and select PreProcess
You will get a huge file with this code near the end
int main ( void )
{
printf("ONE = %d, TWO = %d\n", ONE, TWO );
return 0;
}
Edit: I see it's useless in this case. For some reason the preprocess happens without error and warnings, but the code doesn't change. But if you write useful code you can look at the preprocessed code.
and if you try to compile it you get a bunch of warnings and errors.
test.c:4:1: warning: "ONE" redefined
test.c:2:1: warning: this is the location of the previous definition
test.c:5:1: warning: "TWO" redefined
test.c:3:1: warning: this is the location of the previous definition
test.c: In function ‘main’:
test.c:8: error: ‘ONE’ undeclared (first use in this function)
test.c:8: error: (Each undeclared identifier is reported only once
test.c:8: error: for each function it appears in.)
test.c:8: error: ‘TWO’ undeclared (first use in this function)
conflict of which macro will be called will be arised.....as ONE is 1 and ONE is TWO.... that is linking error.
In the 4th line #define ONE TWO, does the pre processor replace it blindly as 1 2 immediately?
No. The relevant form of the define directive in this case is:
#define identifier replacement-list new-line
... and there is no replacement happening on identifier. Also, the following applies:
An identifier currently defined as an object-like macro shall not be redefined by another #define preprocessing directive unless the second definition is an object-like macro definition and the two replacement lists are identical.
... which makes your redefinition illegal.
If you need to redefine a macro, you have to undefine it first using #undef.