Is it possible to get the total number of items defined by an enum at runtime?
While it's pretty much the same question as this one, that question relates to C#, and as far as I can tell, the method provided there won't work in Objective-C.
An enum is a plain-old-C type, therefore it provides no dynamic runtime information.
One alternative is to use the last element of an enum to indicate the count:
typedef enum {
Red,
Green,
Blue,
numColors
} Color;
Using preprocessors you can achieve this without the annoying 'hack' of adding an additional value to your enum
#define __YourEnums \
YourEnum_one, \
YourEnum_two, \
YourEnum_three, \
YourEnum_four, \
YourEnum_five, \
YourEnum_six,
typedef enum : NSInteger {
__YourEnums
}YourEnum;
#define YourEnum_count ({ \
NSInteger __YourEnumsArray[] = {__YourEnums}; \
sizeof(__YourEnumsArray)/sizeof(__YourEnumsArray[0]); \
})
Related
I'm trying to write myself a little macro to allow me to dynamically link and call a function that has variable arguments. For example, the function I want to call has a method signature that looks like this:
extern void Foo(NSString *bar, NSString *format, ...);
I would like the invocation of my macro to look something like this:
DYNAMIC_LINK_FUNCTION_WITH_VARGS(FooFramework, Foo, void, (NSString *bar, NSString *format), (option, format))
I have an existing macro that I'm trying to adapt to handle this:
#define DYNAMIC_LINK_FUNCTION(framework, functionName, resultType, parameterDeclarations, parameterNames)
Part of which does this:
functionName = (resultType (*) parameterDeclarations) dlsym(Load##framework(), #functionName); \
return functionName parameterNames; \
But I'm not sure where/how to incorporate the "..."
Here's the original macro in its complete form:
#define DYNAMIC_LINK_FUNCTION(framework, functionName, resultType, parameterDeclarations, parameterNames) \
static resultType init##functionName parameterDeclarations; \
static resultType (*dynamicLink##functionName) parameterDeclarations = init##functionName; \
\
static resultType init##functionName parameterDeclarations \
{ \
dynamicLink##functionName = (resultType (*) parameterDeclarations) dlsym(Load##framework(), #functionName); \
return dynamicLink##functionName parameterNames; \
}
How to fetch the row and column number of error (i.e which part of string does not follow the grammar rules)?
I am using yacc parser to check the grammar.
Thank you.
you'd better read the dragon book and the aho book that explain and show example of how to write a lex/yacc based compiler.
In order to get line/column of the error, you shall make your lexer preserve the column and line. So in your lexer, you have to declare two globals, SourceLine and SourceCol (of course you can use better non-camel cased names).
In each token production, you have to calculate the column of the produced token, for that purpose I use a macro as follows:
#define Return(a, b, c) \
{\
SourceCol = (SourceCol + yyleng) * c; \
DPRINT ("## Source line: %d, returned token: "a".\n", SourceLine); \
return b; \
}
and the token production, with that macro, is:
"for" { Return("FOR", FOR, 1);
then to keep lines, for each token that makes a new line, I'm using:
{NEWLINES} {
BEGIN(INITIAL);
SourceLine += yyleng;
Return("LINE", LINE, 0);
}
Then in your parser, you can get SourceCol and SourceLine if you declare those as extern globals:
extern unsigned int SourceCol;
extern unsigned int SourceLine;
and now in your parse_error grammar production, you can do:
parse_error : LEXERROR
{
printf("OMG! Your code sucks at line %u and col %u!", SourceLine, SourceCol);
}
of course you may want to add yytext, handle a more verbose error message etc.. But all that's up to you!
I have a question about enum : when I create an enum, does the latest value will always be higher than the first value of the enum ?
Maybe an exemple will be helpful to understand what I mean :
Imagine I am developing a RPG game, in which there are weapons. Each weapon has a type :
typedef enum
{
WoodenSword,
IronSword,
SteelSword,
GoldenSword
}WeaponType;
Now I want to check the difference of power between the weapons (supposing the WoodenSword is the weakest weapon and the GoldenSword is the strongest weapon). Is it possible de check the power of a weapon doing a simple :
WeaponType type = GoldenSword;
if(type > WoodenSword)
{
//Do something
}
In other words, I don't want this but is it possible for an enum value to be like this (if you don't force the value) :
typedef enum
{
WoodenSword, //-> equals 40
IronSword, //-> equals 0
SteelSword, //-> equals 42
GoldenSword //-> equals 5
}WeaponType;
Or it will be this way by default :
typedef enum
{
WoodenSword, //-> equals 0
IronSword, //-> equals 1
SteelSword, //-> equals 2
GoldenSword //-> equals 3
}WeaponType;
Hope to be clear enough. Please, feel free to tell me if I am not precise enough.
Thanks.
For C:
From the C99 standard section 6.7.2.2 Enumeration specifiers:
The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted.98) An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant. (The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.) The enumerators of an enumeration are also known as its members.
So, if the value of an enum enumerator is not explicitly set it is guaranteed to be one greater than the previous value.
C/C++ guarantees that if you don't force values, any next non-forced value in enum will be previous + 1.
Yes, the default behavior is how you describe. To get the other behavior, you need to set values like this:
typedef enum
{
WoodenSword = 40, //-> equals 40
IronSword = 0, //-> equals 0
SteelSword = 42, //-> equals 42
GoldenSword = 5 //-> equals 5
} WeaponType;
If you don't force subsequent values you can rely on it, unless ...
root#debian:/home/david# cat demo.c
#include <stdio.h>
#include <limits.h>
enum {a = INT_MAX, b};
int main(void)
{
printf("a=%d b=%d\n", a, b);
return 0;
}
root#debian:/home/david# clang -o demo demo.c
demo.c:4:20: warning: overflow in enumeration value
enum {a = INT_MAX, b};
^
1 warning generated.
root#debian:/home/david# ./demo
a=2147483647 b=-2147483648
Or just use defines instead of enumaration
#define IronSword 0
#define GoldenSword 5
#define WoodenSword 40
#define SteelSword 42
and
if(type > WoodenSword)
{
//Do something
}
I'm developing an app for Mac OS, which includes a cross-platform lib in C++. There's a macro defined as follows:
#define MY_GET(DataType,DataName,PtrFunName,DefaultVaule) \
DataType Get##DataName() \
{ \
DataType dataTem = (DefaultVaule);\
if (NULL == p) \
{ \
return dataTem; \
} \
p->Get##PtrFunName(CComBSTR(L#DataName),&dataTem); \
return dataTem; \
}
When compiling, the compiler generates the following error:
Use of undeclared identifier 'L'
Which is expanded from macro 'MY_GET'. After searching for CComBSTR(L, I can find other usage of L"String". So why is the L expanded from my macro is undefined while other L are compiled successfully.
Is L"String" legal in Objective-C?
I seems that you need the preprocessor "token concatenation" operator ## here:
CComBSTR(L ## #DataName)
instead of
CComBSTR(L#DataName)
The following code in an Objective-C file compiles and produces the wchar_t string L"abc":
#define LL(x) L ## #x
wchar_t *s = LL(abc); // expands to: L"abc"
I don't know if other compilers behave differently, but the Apple LLVM 4.1 compiler does not a allow a space between L and the string:
#define LL(x) L#x
wchar_t *s = LL(abc); // expands to: L "abc"
// error: use of undeclared identifier 'L'
im learning cocos2d [open gl wrapper for objective C on iPhone], and now playing with sprites have found this in a example,
enum {
easySprite = 0x0000000a,
mediumSprite = 0x0000000b,
hardSprite = 0x0000000c,
backButton = 0x0000000d,
magneticSprite = 0x0000000e,
magneticSprite2 = 0x0000000f
};
...
-(id) init
{...
/second sprite
TSprite *med = [TSprite spriteWithFile:#"butonB.png"]; //blue
[med SetCanTrack:YES];
[self addChild: med z:1 tag:mediumSprite];
med.position=ccp(299,230);
[TSprite track:med];
so the variable defined in the enum is used in the tag name of the created sprite object,
but i don understand
why give values in hexa to the tags to use
the enum with out tags
as I knew this enum in obj C and C
typedef enum {
JPG,
PNG,
GIF,
PVR
} kImageType;
thanks!
Usually, when you are creating an enum, you want to use it as a type (variable, method parameters etc.).
In this case, it's just a way how to declare integer constants. Since thay don't want to use the enum as type, the name is not necessary.
Edit:
Hexadecimal numbers are commonly used when the integer is a binary mask. You won't see any operators like +,-,*,/ used with such a number, you'll see bitwise operators (!, &, |, ^).
Every digit in a hexadecimal number represents 4 bits. The whole number is a 32-bit integer and by writing it in hexadecimal in this case, you are saying that you are using only the last four bits and the other bits can be used for something else. This wouldn't be obvious from a decimal number.
Enums are automatically assigned values, incremented from 0 but you can assign your own values.
If you don't specify any values they will be starting from 0 as in:
typedef enum {
JPG,
PNG,
GIF,
PVR
} kImageType;
But you could assign them values:
typedef enum {
JPG = 0,
PNG = 1,
GIF = 2,
PVR = 3
} kImageType;
or even
typedef enum {
JPG = 100,
PNG = 0x01,
GIF = 100,
PVR = 0xff
} kImageType;
anything you want, repeating values are ok as well.
I'm not sure why they are given those specific values but they might have some meaning related to use.
Well, you seem to be working off a terrible example. :)
At least as far as enums are concerned. It's up to anyone to define the actual value of an enum entry, but there's no gain to use hex numbers and in particular there's no point in starting the hex numbers with a through f (10 to 15). The example will also work with this enum:
enum {
easySprite = 10,
mediumSprite,
hardSprite,
backButton,
magneticSprite,
magneticSprite2
};
And unless there's some point in having the enumeration start with value 10, it will probably work without specifying any concrete values.