Hurray for constant expressions!

Discussion in 'C Programming' started by luser droog, Jun 2, 2014.

1. luser droogGuest

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

luser droog, Jun 2, 2014

2. Richard BosGuest

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

Richard Bos, Jun 2, 2014

3. luser droogGuest

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) \
I r=AR(w),*d=AD(w),n=AN(w);ARC z; \
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(+) }

luser droog, Jun 3, 2014