Consider:
enum Test
{
a = 3,
b = 7,
c = 1
};
I want to access the enum using an index. Something like this:
for (i=0; i<n; i++)
doSomething((Test)i);
How can I do something like this, where I will be able to access the enum using an index, though the members of the enum have different values?
This is the best you can do:
enum Test { a = 3, b = 7, c = 1, LAST = -1 };
static const enum Test Test_map[] = { a, b, c, LAST };
for (int i = 0; Test_map[i] != LAST; i++)
doSomething(Test_map[i]);
You have to maintain the mapping yourself.
You can't do that. A C enum is not much more than a bunch of constants. There's no type-safety or reflection that you might get in a C# or Java enum.
Your question demonstrates you don't really understand what an enum is for.
It is not something that can be indexed, nor is there ever any reason to. What you have defined is actually just 3 constants named a, b, and c, whose values are 3, 7, and 1 respectively.
As someone else mentioned, this is not the purpose of an enum. In order to do what you are asking, you can simply use an array:
#define a 3
#define b 7
#define c 1
int array[3] = { a, b, c };
int i;
for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) {
doSomething( array[i] );
}
Related
#define PUMP [0,1]
when I call a function like this:
for (index = 0;index < 8; index++)
{
get_motor_current(PUMP[index]);
}
The intent is to do get_motor_current([0][index]) and get_motor_current([1][index])
Thank you very much.
You can do it by having the macro expand into a compound literal.
#include <stdio.h>
#define PUMP ((const int[]){0, 1})
int main(void) {
for (int index = 0;index < 2; index++)
{
printf("%d\n", PUMP[index]);
}
}
Long story short, you can't do what you're trying to do the way you're trying to do it. All the C preprocessor does is perform direct text substitutions. So, after preprocessing, your code snippet would look like:
for (index = 0;index < 8; index++)
{
get_motor_current([0,1][index]);
}
which is not valid C.
Also, square brackets [] are only used for indexing an existing array. If you want to initialize an array with a list of values, you write a list of values enclosed in curly braces {} like so:
int some_array[] = {1, 2, 3, 4};
You don't need to define an array size here (i.e. say some_array[4]) because the compiler just counts the number of items in the list and does that for you.
if I have enum:
typedef enum
{
A= 0,
B= 1,
C =2,
D= 4,
E= 6,
F= 8,
G= 10,
MAX_ELEMENTS
}my_enum
How can I declare the number of elements within enum without one element?
something like this:
uint8 enum_numb_elements = MAX_ELEMENTS - 1
This is not a good practice to do arithmetic operation on enums. Is there an other way?
You can define it, sort of, but it involves some boiler-plate that isn't all too pleasant, and pollutes the global/tag namespace a lot/bit.
If you leverage the notorious X macros for the job, it would look like this:
#define LIST_OF_ENUM_IDS \
X(A, 0) \
X(B, 1) \
X(C, 2) \
X(D, 4) \
X(E, 6) \
X(F, 8) \
X(G, 10)
#define X(id, val) \
id = val,
typedef enum
{
LIST_OF_ENUM_IDS
} my_enum;
#undef X
#define X(id, val) id##_impl_helper,
enum my_enum_impl_helper__ {
LIST_OF_ENUM_IDS
MY_ENUM_MAX_ELEMENTS
};
#undef X
Live example: On Ideone
Alternatively, some shops will instead rely on bold comments and code reviews to catch such things:
/********************************************
*
**
*** ATTENTION! Remember to bump MAX_ELEMENTS
*** should you add new values to the enum
**
*
********************************************/
typedef enum
{
A= 0,
B= 1,
C =2,
D= 4,
E= 6,
F= 8,
G= 10,
MAX_ELEMENTS = 7 /// Bump this if you add new values!
}my_enum;
Which can work not all too bad, despite the human factor.
I prefer to keep enums contiguous to exploit the 'features' of C..
typedef enum
{
A,
B,
C,
D,
E,
F,
G,
MAX_ELEMENTS
} my_enum;
int element_array[MAX_ELEMENTS] =
{
0,
1,
2,
4,
6,
8,
10
};
Given this construct, NUM_ELEMENTS adjusts automatically if you add/subtract enums, and you can use my_elem in for loops, etc. The major issue of concern is that you need to remember to maintain element_array in conjunction with my_enum when you add or remove enums.
A for loop example
my_elem elem;
for (elem = (my_elem)0; elem < MAX_ELEMENTS; elem++)
{
printf("The value of element %d is %d\n", elem, element_array[elem] );
}
this is my first question here, please notice I'm very new to coding. Quick search doesn't helped me since I think the answer might be too simple.
Im writing some code in CAPL (a CANoe specific language based on C).
Lets have my scenario simplified: I have to read 10 values Input, but I'm just able to read one by a time (due to HW reasons).
My value is stored in a buffer (rsBuf), now I'm trying to define a help-array for everytime I read the value (rsBuf1 ... 10).
At the end I will create another array with added values of rsBuf1 ... rsBuf10.
for every "read-action", I want to define
rsBuf1 = rsBuf;
rsBuf2 = rsBuf; and so on...
error: for "rsBuf1 = rsBuf;" Error 1112 at (732,16): operand types are incompatible.
Compilation failed -- 1 errors, 0 warnings
my "real" values:
variables
{
byte rsBuf[1024];
byte rsBuf1[1024];
}
is there an easy way to do this one-array-from-another?
I also tried some other notations I found, like rsBuf1 = {rsBuf}, but wasn't helping. Of course I could define
rsBuf1[1]=rsBuf[1];
...
rsBuf1[1024]=rsBuf[1024];
but that would be a waste of time I guess.
Thanks in advance, cheers Robert
You can't copy arrays through assignment in C, because the syntax does not allow it. The best solution is to use the memcpy function.
Alternatively, if it makes sense for the program design, you could put the arrays inside a wrapper struct:
typedef struct
{
int array [5];
} array_wrapper_t;
array_wrapper_t this = {1,2,3,4,5};
array_wrapper_t that;
that = this;
This should yield identical machine code as a call to memcpy.
Option 1
You can use memcpy as follows to copy the entire array:
memcpy(rsBuf1, rsBuf, elcount(rsBuf));
The following would copy the first four bytes:
memcpy(rsBuf1, rsBuf, 4);
Option 2
Optionally you could define your copy-function, see the copy_buffer() implementation:
variables
{
byte rsBuf[1024] = {1, 2, 3, 4, 5, 6, 7, 8};
byte rsBuf1[1024];
}
on start
{
print_buffer(rsBuf, 8);
print_buffer(rsBuf1, 8);
copy_buffer(rsBuf1, rsBuf, elcount(rsBuf));
print_buffer(rsBuf1, 8);
}
void copy_buffer(byte dest[], byte src[], long len)
{
int i;
for (i = 0; i < len; i++)
dest[i] = src[i];
}
void print_buffer(byte buf[], byte len)
{
int i;
writeLineEx(0, 0, ">");
for (i = 0; i < len; i++)
writeEx(0, 0, " 0x%02x", buf[i]);
}
Consider the following code i managed to write:
#include <stdio.h>
#define FOR(A, B, C) for(A; B; C++)
int main()
{
FOR(i=0, i<10, i)
printf("%i", i);
return 1;
}
The output is:
0123456789
If i do FOR(i=5, i<10, i)
then respectively the output is 56789
My questions are is that legal? Will it cause any errors in different cases? Does it works exactly like a for loop?
Yes it's a "legal" macro, but no, it does not work like a real for loop.
Your macro won't handle this:
int a, b;
for(a = 0, b = 4711; a < b; ++a);
for instance, since you can't distinguish the , used to build a longer initializing expression to the one used to separate the expressions that make up the parts:
FOR(a = 0, b = 0, a < b, ++a);
will break, since it looks like a call with 4 arguments instead of 3.
A macro is just copied everywhere the preprocessor sees you using the macro keyword. It just copies the text, nothing more.
To elaborate on that a bit more, consider this example:
#define MY_MACRO a
int MY_MACRO = 5;
When the preprocessor comes along it will take the above and change it to:
int a = 5;
and then the compiler will come along and compile it like normal C/C++ code.
When you add arguments to your macro, they are just substituted in place within your macro. This can be a problem, consider the following two macros:
#define BAD_MACRO(a, b) a*b
#define GOOD_MACRO(a, b) (a)*(b)
They look almost the same, but consider the following:
int k = BAD_MACRO(2, 3); // k = 2*3 = 6
int j = GOOD_MACRO(2, 3); // j = 2*3 = 6
int m = BAD_MACRO(2+1, 3); // m = 2+1*3 = 5
int n = GOOD_MACRO(2+1, 3); // n = (2+1)*3 = 9
Although note that neither of these macros are good or bad, they just don't have the same behaviour as a typical function.
Here I know that the following code simply copies the character i rather than its value to the preprocessor statement (which makes a error for undefined symbol i in compile-time).
What I want is:
Is their a way such that the compiler treats, i as a variable with some value rather than a character ?
#include <stdio.h>
#define PRINT(x) printf("%d \n", y ## x)
int main(void) {
int y1=0 , y2=1 , y3=4;
for(int i=1; i <= 3; ++i) {
PRINT(i);
}
return 1;
}
About the pre-processor
First of all, I think there's a need to clarify how the preprocessor works: it pre-processes the input files, which means it runs before the compiler. Unfortunatly, for historical reasons, it doesn't know anything about C or C++, doesn't parse anything, and just does very simple textual operations on words and parenthesis. Just to illustrate my point:
#define this __FILE__
#define file -- Hell no!
#define fine(a, b) fine: a ## _ ## b
Ok, so this is not a valid C or C++ file
But the preprocessor will run just fine(go, try!)
Run this with a pre-processor, for example gcc -x c -E -P test.txt and you'll get:
Ok, so "test.txt" is not a valid C or C++ -- Hell no!
But the preprocessor will run just fine: go_try!
So, obviously, when the preprocessor sees PRINT(i) in your code, it replaces it with printf("%d \n", yi) without thinking much about it. And it has absolutely no idea i is a variable, don't even think about evaluating it's value.
Solutions
Basically, what you want is print a bunch of numbers.
You could simply do
printf("0\n1\n4\n");
But this lacks makes changing numbers cumbersome,
so let's go with
printf("%d\n%d\n%d\n", 0, 1, 4);
Which makes it easy to change a number, but not to add/remove one.
Ok so how about:
printf("%d\n", 0);
printf("%d\n", 1);
printf("%d\n", 4);
Yeah, you can change/add/remove numbers easily but as any sane programmer you hate repetition. So, we need some kind of loop.
By far the simplest and most straightforward way to iterate in C is at runtime, using an array:
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/sizeof(int); ++i) {
printf("%d\n", y[i]);
}
If you want, you can hide the printf using a function:
inline void print_int(int* y, int i) { print_int(y[i]); }
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/4; ++i) print_int(y, i);
And going further with functions:
inline void print_int(int x) { printf("%d\n", x); }
inline void print_int(int* y, int i) { print_int(y[i]); }
inline void print_ints(int * y, int n)
{
for(int i = 0; i < n; ++i)
print_int(y, i);
}
template<int n> // C++
inline void print_ints(const int[n] & y) { print_ints(&y[0], n); }
int [] y = { 0, 1, 4 };
print_ints(y); // C++
// or in C:
print_ints(y, sizeof(y)/sizeof(int));
Now, what if you absolutely want the generated code to look like solution 3. ? This means you need the iteration to happen at compile-time. Tricky!
That's where the preprocessor can come into play. There are (hacky) ways to make it do this kind of things. I strongly recommend not implementing this yourself (except to play), but use the Boost.preprocessor library instead:
#define PRINTER(R,D, NUMBER) printf("%d\n", NUMBER);
#define NUMBERS (0, 1, 4)
BOOST_PP_LIST_FOR_EACH(PRINTER, _, BOOST_PP_TUPLE_TO_LIST(NUMBERS))
// will expand to printf("%d\n", 0); printf("%d\n", 1); printf("%d\n", 4);
Under standard C, this is not possible; during preprocessing, the compiler simply sees the identifier i as simply that - an identifier. It does not know that i is of type int, or that it's even a variable in the first place.
The easiest way to achieve what's intended is to use an array, like so:
int i;
int y[] = { 0, 1, 4 };
for (i = 0; i < 3; i++) // NOTE: arrays in C start at index 0, not 1
{
printf("%d \n", y[i]);
}
Also note that I got rid of the macro, as you want to use the value of a runtime variable i to select another runtime variable.