I have a program that I'm trying to decode. It is translated to C from another language (whose name is not spoken here), and as I want to understand how it works, I am slowly rewriting the code and simplifying it to use all the nice logical constructs C has to offer.
The following little bit keeps popping up in my code, with varying values of X
and Y
:
ptr[X]--;
while(ptr[X])
{
ptr[X]--;
ptr += Y;
}
ptr
is of type char *
, and I can't really make assumptions about the state of the array at any point because it's pretty deeply embedded in loops and dependent on input and output. I can successfully "simplify" that to:
for(ptr[X]--; ptr[X]; ptr[X]--, ptr += Y);
But that's just awful. Ever so slightly better is:
for(ptr[X]--; ptr[X]; ptr += Y) ptr[X]--;
I want to know if anyone can come up with a better simplification of the above code, I would greatly appreciate it. This occurs in no less than five places, and is impairing my ability to simplify and understand the flow control, so if anyone can provide a more consise/readable version, that would be awesome. If anyone can just offer any sort of fancy insight into that code, that would be awesome too, although I basically understand what it does.
Insight into the code for a specific X
and/or Y
can also help. Y
tends to be between -2 and 2, and X
is usually 1, for what its worth.
ptr[X]
is equivalent to *(ptr + X)
, so we can rewrite it as follows:
for((*(ptr + X))--; *(ptr + X); (*(ptr + X))--, ptr += Y);
Now there's a lot of redundancy here, so we can simplify this to:
char *ptr_plus_x = ptr + X;
for((*ptr_plus_x)--; *ptr_plus_x; (*ptr_plus_x)--, ptr_plus_x += Y);
Then we can get rid of ptr_plus_x
entirely:
ptr += X;
for((*ptr)--; *ptr; (*ptr)--, ptr += Y);
In English, we visit the memory locations at offsets X, X+Y, X+2Y, X+3Y, ..., decrementing each memory location, until we find a memory location that is 0. But, the test for 0 always occurs after the decrement, so we're really looking for the first memory location in that sequence with a value of 1. Once we find that, we decrement it to 0 and quit.
If Y is 1, then we decrement a string of consecutive memory locations going forwards, up to and including the first 1. If Y is -1, the same thing happens, but searching backwards from offset X. If Y is 0, an infinite loop occurs. If Y is any other value, the search pattern skips various entries.
It's not a very intuitive function, so I can see why you're confused.
I'll throw in:
ptr[X]--
while (ptr[X]--) ptr+=Y;
first evaluate, then decrement (for while condition, that is)
Edit: OK, i'll hate myself in the morning. Goto's are ok at this level, right?
dec: ptr[x]--
while (ptr[X]){
ptr+=Y;
goto dec;
}
(i honestly dont know whether to leave this or not.)
EDIT2: so, how about this one? (tcc didn't complain)
while (ptr[X]--?ptr[X]--,ptr+=Y:0){}
EDIT 2 1/2;
//longshot
while (ptr[X]--?ptr[X]--,ptr+=Y, ptr[X]:0){}
If all else fails..
EDIT3: Last one for tonight.
while (ptr[X]--?ptr[X]--,ptr+=Y:0){
if (!ptr[X]) break;
}//good luck with this, it has been very amusing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With