Increment a number in compile time macro

B

Bin Chen

switch(i) {
case 1:
break;
case 2:
break;
[...]
case N:
break;

}

Now, after some time I want to add a 'case 2' between case 1 and case
2, the result means every case number after case 2 need to be
incremented by 1, it there a macro tricks to make life easier? Such
as:

switch(i) {
case AUTO_INC_MACRO:
break;
case AUTO_INC_MACRO:
....

Thanks in advance.

Bin
 
I

Ian Collins

Bin said:
switch(i) {
case 1:
break;
case 2:
break;
[...]
case N:
break;

}

Now, after some time I want to add a 'case 2' between case 1 and case
2, the result means every case number after case 2 need to be
incremented by 1, it there a macro tricks to make life easier? Such
as:
Use an enum. Never use magic numbers.
 
B

Barry Schwarz

switch(i) {
case 1:
break;
case 2:
break;
[...]
case N:
break;

}

Now, after some time I want to add a 'case 2' between case 1 and case
2, the result means every case number after case 2 need to be
incremented by 1, it there a macro tricks to make life easier? Such
as:

switch(i) {
case AUTO_INC_MACRO:
break;
case AUTO_INC_MACRO:

Macros don't perform calculations. They only perform text
substitution. And a subsequent appearance of a macro in your code
will not have access to the result of a previous appearance.

However, you can do what you want with an enum. Something of the form
enum {CASE1=1, CASE2, ..., CASEN};
and change each case label to
case CASE1:
...
case CASE2:
etc.

Later, when you want to insert a case between CASE1 and CASE2, change
you enum to
enum {CASE1=1, CASE1A, CASE2, ..., CASEN};
and insert the new block of code immediately before the CASE2 label.

To eliminate the rampant confusion after a half-dozen insertions where
CASE6 may be 7 while CASE10 is 13, I would suggest using identifiers
that are suggestive of the function to be performed rather than their
numeric value. Something like
enum {INSERT=1, DELETE, EDIT, COMPUTE};
and then you could later amend it to
enum {INSERT=1, DELETE, EDIT, PRINT, COMPUTE};
 
N

Nick Keighley

switch(i) {
case 1:
  break;
case 2:
  break;
[...]
case N:
  break;

}

Now, after some time I want to add a 'case 2' between case 1 and case
2, the result means every case number after case 2 need to be
incremented by 1, it there a macro tricks to make life easier? Such
as:

switch(i) {
case AUTO_INC_MACRO:
  break;
case AUTO_INC_MACRO:
...

how about

#include <stdio.h>

#define INC(N) (N + 1)

int main (void)
{
int i = 2;

switch (i)
{
case INC(1):
printf ("A\n");
break;

case INC(2):
printf ("B\n");
break;
}

return 0;
}

would this work? Though pre-processor magic of this
sort is usually not a good idea.
 
B

Ben Bacarisse

Nick Keighley said:
switch(i) {
case 1:
  break;
case 2:
  break;
[...]
case N:
  break;

}

Now, after some time I want to add a 'case 2' between case 1 and case
2, the result means every case number after case 2 need to be
incremented by 1, it there a macro tricks to make life easier? Such
as:

switch(i) {
case AUTO_INC_MACRO:
  break;
case AUTO_INC_MACRO:
...

how about

#include <stdio.h>

#define INC(N) (N + 1)

int main (void)
{
int i = 2;

switch (i)
{
case INC(1):
printf ("A\n");
break;

case INC(2):
printf ("B\n");
break;
}

return 0;
}

would this work? Though pre-processor magic of this
sort is usually not a good idea.

It's not really magic is it? INC(1) is just a funny way to write 2
(as a constant expression). Are you suggesting the OP uses some
search-and-replace to change case x: into case INC(x): for the x
greater then the one they want to add, thus permitting the new case to
be "slotted in"? If so, then the editor is almost certainly capable of
doing the arithmetic itself. If not, then I'm not sure how the INC
macro helps.

Any literal answer almost misses the point, for me. If the OP is
adding cases in the middle of an existing range, surely all sorts of
other parts of the code much change too. Switching to an enum will
automatically fix these as well (once all the constants are replaced by
enum names).
 
M

Moi

switch(i) {
case 1:
break;
case 2:
break;
[...]
case N:
break;

}

Now, after some time I want to add a 'case 2' between case 1 and case 2,
the result means every case number after case 2 need to be incremented
by 1, it there a macro tricks to make life easier? Such as:

switch(i) {
case AUTO_INC_MACRO:
break;
case AUTO_INC_MACRO:
...

#include <stdio.h>

#define SWITCH(v) switch ((2*(v))+__LINE__-1)
#define CASE case __LINE__

int main(int argc, char *argv[] )
{
int ii;

SWITCH(argc) {
CASE:
printf("One!!\n"); break;
CASE:
printf("two!!\n"); break;
CASE:
printf("three!!\n"); break;
CASE:
printf("four!!\n"); break;
default:
printf("Unknown %d. Please call QA.\n", argc); break;
}
return 0;
}



HTH,
AvK
;-)
 
B

Barry Schwarz

switch(i) {
case 1:
break;
case 2:
break;
[...]
case N:
break;

}

Now, after some time I want to add a 'case 2' between case 1 and case 2,
the result means every case number after case 2 need to be incremented
by 1, it there a macro tricks to make life easier? Such as:

switch(i) {
case AUTO_INC_MACRO:
break;
case AUTO_INC_MACRO:
...

#include <stdio.h>

#define SWITCH(v) switch ((2*(v))+__LINE__-1)
#define CASE case __LINE__

int main(int argc, char *argv[] )
{
int ii;

SWITCH(argc) {
CASE:
printf("One!!\n"); break;
CASE:
printf("two!!\n"); break;
CASE:
printf("three!!\n"); break;
CASE:
printf("four!!\n"); break;
default:
printf("Unknown %d. Please call QA.\n", argc); break;
}
return 0;
}

Not bad if the requested flexibility ever becomes a higher priority
than readability. Non-trivial cases could have some pretty long
lines. And let's hope none of the statements within a case contain
any macros that might expand to more than one line.
 
H

Harald van Dijk

And
let's hope none of the statements within a case contain any macros that
might expand to more than one line.

A macro can't expand to more than one line.
 
B

Barry Schwarz

A macro can't expand to more than one line.

Then the hope is not in vain :)

For my education, you are saying the preprocessor will merge the lines
in macros like
do {\
many lines of code each ending with \
} while(0);
which is often recommended here? Somehow I had the idea the merging
took place during compilation.

Which raises a new question. As far as the __LINE__ macro is
concerned, is the following code one line or two?
x = 1;\
y = 3;
On my system, the answer is two but n1256 (5.1.1.2-2) seems to imply
it should be one.
 
H

Harald van Dijk

Then the hope is not in vain :)

For my education, you are saying the preprocessor will merge the lines
in macros like
do {\
many lines of code each ending with \
} while(0);
which is often recommended here?

Yes. This happens before the macro definition is even parsed.
Somehow I had the idea the merging
took place during compilation.

It's done in translation phase 2, while handling of preprocessor
directives such as #define is translation phase 4.
Which raises a new question. As far as the __LINE__ macro is concerned,
is the following code one line or two?
x = 1;\
y = 3;
On my system, the answer is two but n1256 (5.1.1.2-2) seems to imply it
should be one.

It should be one.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top