Hurray for constant expressions!

L

luser droog

Trying to simplify some nested switch statements
over enum values. Expressions saves the day.

#include<stdio.h>

enum { X=1, Y=2 };

int pair(int a, int b){
return a*(Y+1)+b;
}

int switchpair(int p){
switch(p){
case 0:
printf("0\n"); break;
case Y:
printf("Y\n"); break;
case X*(Y+1):
printf("X\n"); break;
case X*(Y+1)+Y:
printf("XY\n"); break;
}
return 0;
}

int main(){

int x;
x = pair(X,Y);
switchpair(x);
x = pair(0,Y);
switchpair(x);
x = pair(X,0);
switchpair(x);
x = pair(0,0);
switchpair(x);

return 0;
}

Output:

XY
Y
X
0

R

Richard Bos

luser droog said:
Trying to simplify some nested switch statements
over enum values. Expressions saves the day.

enum { X=1, Y=2 };

int pair(int a, int b){
return a*(Y+1)+b;
}

int switchpair(int p){
switch(p){
case 0:
printf("0\n"); break;
case Y:
printf("Y\n"); break;
case X*(Y+1):
printf("X\n"); break;
case X*(Y+1)+Y:
printf("XY\n"); break;
}
return 0;
}

It works, but it's a maintenance nightmare. At the very least add a
SWITCHHACKMAX value, in case you want to later add Z and X2 (and then,
three years later, Y2017, and...), and write a*(SWITCHHACKMAX+1)+b
instead of relying on Y always being the largest value. Also, change
pair() to a macro, so you can use it in switchpair() as well - self-
documenting code is always better - like this:

enum { X=1, Y=2, SWITCHHACKMAX };
/* Use a shorter name for SWITCHHACKMAX if you must, but it only
appears in these two lines, so why would you? */

#define PAIR(a, b) (a)*(SWITCHHACKMAX+1)+(b);

int switchpair(int p){
switch(p){
case PAIR(0,0):
printf("0\n"); break;
case PAIR(0,Y):
printf("Y\n"); break;
case PAIR(X,0):
printf("X\n"); break;
case PAIR(X,Y):
printf("XY\n"); break;
}
return 0;
}

And, whatever you do - comment this! It's hack code, it requires
commenting.

Richard

L

luser droog

It works, but it's a maintenance nightmare. At the very least add a
SWITCHHACKMAX value, in case you want to later add Z and X2 (and then,
three years later, Y2017, and...), and write a*(SWITCHHACKMAX+1)+b
instead of relying on Y always being the largest value. Also, change
pair() to a macro, so you can use it in switchpair() as well - self-
documenting code is always better - like this:

enum { X=1, Y=2, SWITCHHACKMAX };
/* Use a shorter name for SWITCHHACKMAX if you must, but it only
appears in these two lines, so why would you? */

#define PAIR(a, b) (a)*(SWITCHHACKMAX+1)+(b);

int switchpair(int p){
switch(p){
case PAIR(0,0):
printf("0\n"); break;
case PAIR(0,Y):
printf("Y\n"); break;
case PAIR(X,0):
printf("X\n"); break;
case PAIR(X,Y):
printf("XY\n"); break;
}
return 0;
}

And, whatever you do - comment this! It's hack code, it requires
commenting.

Yes, the macro is better for this.
The application is *all* hack-code, but I did hazard a single comment
in accordance with your suggestion. This extract shows some of the
context where I'm using this hack.

from https://github.com/luser-dr00g/inca/blob/master/inca2.c

#define CASE break;case
enum types { NUL, CHR, INT, DBL, BOX, FUN, NTYPES };
//TPAIR() combines types into a single value that can be switch()ed
#define TPAIR(a,b) ((a)*NTYPES+(b))

#define V2(f) ARC f(ARC a,ARC w)
#define DO(n,x) {I i=0,_n=(n);for(;i<_n;++i){x;}}

#define MATHOP2(op) \
switch(TPAIR(AT(a),AT(w))) { \
CASE TPAIR(INT,INT): \
z=ga(INT,r,d); DO(n,AV(z)=AV(a) op AV(w)); \
CASE TPAIR(INT,DBL): \
z=ga(DBL,r,d); DO(n,((D*)AV(z))=AV(a) op ((D*)AV(w))); \
CASE TPAIR(DBL,INT): \
z=ga(DBL,r,d); DO(n,((D*)AV(z))=((D*)AV(a)) op AV(w)); \
CASE TPAIR(DBL,DBL): \
z=ga(DBL,r,d); DO(n,((D*)AV(z))=((D*)AV(a)) op ((D*)AV(w))); \
} R z;

V2(plus){ MATHOP2(+) }

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.