C switch case values cannot be modified within the switch (not constant) - c

I am trying to create bounce dynamics in a game that I'm programming on an arduino uno.
I can create a series of nested ifs but I've heard that a switch is faster.
I know that the case values are specified to be constants, but I'm curious if it's possible to make this code work?
// player and ball are both byte arrays
switch(ball[0]) { // bounce off edges x-axis
case (player[0]-1):
ball[3] -= 2;
break;
case player[0]:
ball[3] -= 1;
break;
case (player[0]+3):
ball[3] += 1;
break;
case (player[0]+4): // At this line the compiler says: the value of 'player' is not usable in a constant expression
ball[3] += 2;
break;
}
I'm pretty sure that the answer is either no, or that the workaround of putting the variables into constants will be much slower and larger than simply giving in to the nested ifs, but it doesn't hurt to ask.

Avi Berger presented a fantastic solution which I was able to fit and to make work:
// player and ball are both byte arrays
switch(ball[0] - player[0]) { // bounce off edges x-axis
case 1:
ball[3] -= 2;
break;
case 0:
ball[3] -= 1;
break;
case -3:
ball[3] += 1;
break;
case -4:
ball[3] += 2;
break;
}

Related

What is the fastest way to reverse a power of two in C?

In the equation :
What is the fastest way in C language to find x with a given power of two value (a) ?
Edit :
The mathematical exact solution is :
As (a) is a positive integer and a power of two (no rational number, no equal to zero), this problem can be simplified as "looking for position of set bit".
This post is focused on lite embedded CPU systems. For example : ARM CORTEX M4.
a to x results :
a | x
-------
1 | 0
2 | 1
4 | 2
8 | 3
16 | 4
32 | 5
64 | 6
128 | 7
256 | 8
512 | 9
...
Option 1 : The dirty loop
unsigned int get_power_of_two_exponent(unsigned int value)
{
unsigned int x = 0;
while( ( 1 << x ) != value)
{
x ++;
}
return x;
}
Option 2 : The weird trick
#include <stdint.h>
#if defined(__GNUC__)
static int highest_bit_set(uint32_t value)
{
if (sizeof (unsigned int) == sizeof value)
return 31 - __builtin_clz(value);
else
if (sizeof (unsigned long) == sizeof value)
return 31 - __builtin_clzl(value);
else
exit(127); /* Weird architecture! */
}
#endif
Any faster options ?
Fastest in C is almost always look-up tables, at the expense of memory use. Assuming that the value is always exactly a power of 2, you can make a look-up table like this:
uint8_t get_exponent (uint8_t val)
{
static const uint8_t byte[256] =
{
[1] = 0,
[2] = 1,
[4] = 2,
[8] = 3,
[16] = 4,
[32] = 5,
[64] = 6,
[128] = 7,
};
return byte[val & 0xFF];
}
It will return 0 in case you pass a value which isn't a power of 2.
This can be expanded further either by looping through for example the 4 bytes of a uint32_t and do 4 table-lookups. Or by making even bigger look-up tables.
On x86 I get the above to boil down to this tiny, branch-free machine code:
get_exponent:
movzx edi, dil
movzx eax, BYTE PTR byte.2173[rdi]
ret
(Swapping to uint_fast8_t gives identical code in this case.)
This answer is in dispute - see comment.
The fastest way, somewhat facetiously1, is to write
switch (a)
{
case 1: return 0;
case 2: return 1;
case 4: return 2;
...
Clearly there are as many labels as there are bits in the type, but this is still O(1).
You could even truncate a to a power of two using the idiom a ^ (a & (a - 1)), at the expense of portability given that only works if a is a 2's complement type.
1Although in C++ you could get the compiler to build the table with constexpr and metaprogramming techniques.
The best performances (on my embedded ARM CORTEX M4 CPU core) are obtained with :
Builtin CLZ solution (Count Leading Zero’s)
Moreover, the CLZ solution is by far much more memory efficient than the lookup table method which take the second place.
Often, the LookUp table method still less efficient than the Builtin CLZ because the table is stored in RAM like a DDR for example. Thus, it can takes a dozen of cycle to access the data in this kind of RAM. In this example, this is amplified by the fact that the instruction cache is enabled but not the data cache. Besides, having this huge table stored in cache would not have been very appropriate.
It depends how big values you would like to search, and if there's the biggest possible input defined.
If x can be, for example, 100, searching from beginning (x = 0) with step x++, isn't elegant and optimized (100 checks). You can set step x+=5. If the result is lower than searched value, x+=5. If bigger - step back with x-- (max 4 Times). Size of step you can adjust to your needs.
If there's a "top-limit", you can create an array of possible x and implement binary search.
#Lundin's answer seems the best in terms of speed (just 3 assembly instructions!), but it may not be a good option for your embedded system. If huge LUTs are not an option:
The weird trick seems to be the a fast option, I guess (you should benchmark each option and see actual results, though). You could use that one in case it exists, and fallback to the usual shifting otherwise:
#include <stdint.h>
static int get_pow2_exp(uint32_t value)
{
#if defined(__GNUC__)
if (sizeof(unsigned int) == sizeof(value))
return 31 - __builtin_clz(value);
if (sizeof(unsigned long) == sizeof(value))
return 31 - __builtin_clzl(value);
#endif
int x;
for (x = -1; value; value >>= 1)
x++;
return x;
}
If you want to ensure that it is a power of two, you may use popcnt. Your while loop is an infinite loop in case the input is not a power of two, while mine just gives a solution based on the highest bit (which may be incorrect, depending on your needs).
2^x = a is the equation
Assuming 32 bit architecture and 'a' & 'x' as integers.
Here is my approach
uint32_t x;
uint8_t *ptr ;
uint8_t ByteNo,BitNo,i;
void My_Function(uint32_t a)
{
ByteNo = BitNo = 9;//some random number
ptr = (uint8_t*)&a;//Assuming points to LSB in variable a
for(i=0;i<4;i++)
{
switch(*ptr)
{
case 0x01: BitNo=0;break;
case 0x02: BitNo=1;break;
case 0x04: BitNo=2;break;
case 0x08: BitNo=3;break;
case 0x10: BitNo=4;break;
case 0x20: BitNo=5;break;
case 0x40: BitNo=6;break;
case 0x80: BitNo=7;break;
case 0x00: BitNo=9;break;
default : break;//take care error condition
}
if(9 != BitNo)
{
break;
}
else
{
ptr++;
}
}//for loop
ByteNo = i;
x = (BitNo) + (ByteNo*8);
}//My_Function
Another approach:
switch(a)
{
case 0x00000001: x=0; break;
case 0x00000002: x=1; break;
case 0x00000004: x=2; break;
case 0x00000008: x=3; break;
case 0x00000010: x=4; break;
case 0x00000020: x=5; break;
case 0x00000040: x=6; break;
case 0x00000080: x=7; break;
case 0x00000100: x=8; break;
case 0x00000200: x=9; break;
case 0x00000400: x=10; break;
case 0x00000800: x=11; break;
case 0x00001000: x=12; break;
case 0x00002000: x=13; break;
case 0x00004000: x=14; break;
case 0x00008000: x=15; break;
case 0x00010000: x=16; break;
case 0x00020000: x=17; break;
case 0x00040000: x=18; break;
case 0x00080000: x=19; break;
case 0x00100000: x=20; break;
case 0x00200000: x=21; break;
case 0x00400000: x=22; break;
case 0x00800000: x=23; break;
case 0x01000000: x=24; break;
case 0x02000000: x=25; break;
case 0x04000000: x=26; break;
case 0x08000000: x=27; break;
case 0x10000000: x=28; break;
case 0x20000000: x=29; break;
case 0x40000000: x=30; break;
case 0x80000000: x=31; break;
default: break;//error condition
}

Hexadecimal Number convertor

i trying to write a Recursion function that get a decimal number and print the value in hexadecimal
but i dont know what worng in my code
please help me i still new in Recursion and dont get it complitly...
my code:
void PrintHexadecimalNumber(int n)
{
if (n%16==0)
return ;
PrintHexadecimalNumber(n/16);
switch ((n % 16))// A-F cases
{
case (10):
printf("A");
break;
case (11):
printf("B");
break;
case (12):
printf("C");
break;
case (13):
printf("D");
break;
case (14):
printf("E");
break;
case (15):
printf("F");
break;
}
if ((n%16)<10)
printf(n%16);
}
Your code isn't going to work because of the test you've written to stop the recursion.
if (n%16==0)
If you have the number (in hex) 10, the function will stop immediately because n % 16 will be 0. What you actually want to test for is when n is 0. Like this
if (n==0)
Your switch statement should also be expanded out to include the values 0 to 9 rather than having a separate if statement after it. You can group them together by leaving out the break
switch(n % 16)
{
/* existing case statements go here */
case 0:
case 1:
case 2:
...
case 9:
printf("%d",n % 16); // also fixing this as per comments above.
break;
}
Or you could just use printf("%x",n % 16) and do away with the switch completely if what you're trying to do is explore how recursion works.

How can I use ranges in a switch case statement in C?

My logic is:
if number is between 1 to 10, execute first case statement
if number is from 20 to 30, execute second case statement
is there a solution other than the one below?
case '1' ... '10':
case '20' ... '30':
The GCC compiler supports, as a language extension, case ranges like:
switch(i) {
case 0 ... 9: return true;
default: return false;
}
This language extension is also accepted by Clang/LLVM. So use it if you can afford restricting your code to GCC & Clang compilers.
See also this.
I have no idea why this extension was not included in C11 standard.
Notice also that GCC accepts computed or indirect goto and labels as values. There are cases (in particular in
generated C code) where these features are useful. Examples could include some efficient bytecode interpreter. Some implementations of the Ocaml virtual machine are a good example.
void SwitchDemo(int value)
{
switch(value / 10)
{
case 0: ...; break; // 0 - 9
case 1: ...; break; // 10 - 19
...
}
}
or, specific to the question ranges:
void SwitchDemo(int value)
{
switch((value-1) / 10)
{
case 0: ...; break; // 1 - 10
case 1: ...; break; // 11 - 20
...
}
}
Option 1: use case 0 for 0-9, case 1 for 11-20 and so on.
Option 2: use if
Option 3:
Another shabby way is using fall through cases like this:
#include <stdio.h>
int main(void) {
int i=1;
for(i=1;i<=25;i++)
{
switch(i)
{
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
printf("%d is in between 1-10\n", i);
break;
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
printf("%d is in between 11-20\n", i);
break;
default:
printf("%d is above 20\n", i);
}
}
return 0;
}
Output:
1 is in between 1-10
2 is in between 1-10
3 is in between 1-10
4 is in between 1-10
5 is in between 1-10
6 is in between 1-10
7 is in between 1-10
8 is in between 1-10
9 is in between 1-10
10 is in between 1-10
11 is in between 11-20
12 is in between 11-20
13 is in between 11-20
14 is in between 11-20
15 is in between 11-20
16 is in between 11-20
17 is in between 11-20
18 is in between 11-20
19 is in between 11-20
20 is in between 11-20
21 is above 20
22 is above 20
23 is above 20
24 is above 20
25 is above 20
https://ideone.com/Cw6HDO
C doesn't support case values other than single integers (or integer-like things -- characters, enumeration values). So your options are:
As suggested by pzaenger in a now-deleted comment: transform the number you're working with into something you can switch on (in this case, divide by 10).
Multiple case statements (taking advantage of fallthrough): case 1: case 2: case 3: ... case 10: do_something();
Use if rather than case.
In the C programming language the case statement used in a switch() statement must specify a value that the compiler can turn into a constant in some way. Each of the values used in the case statements must be unique within the scope of the switch(). The default keyword indicates the default if none of the case statements match the expression in the switch() statement.
As an aside, check out Duff's Device to show an interesting use of switch() and case. See How does Duff's device work?
So the following shows several examples of proper case statements in a switch():
#define XXVAL 2
#define CASETEST(x) (x + 5)
int iValue;
// set the value of the variable iValue at some point
switch (iValue) {
case 0:
// do the case if iValue == 0
break;
case XXVAL:
// do the case if iValue == XXVAL
break;
case CASETEST(3):
// do the case if iValue == CASETEST(3)
// works because preprocessor generates the source text which is
// then compiled and the expression can be resolved to a constant
break;
case CASETEST(5) * 2:
// do the case if iValue == CASETEST(5) * 2
// works because preprocessor generates the source text which is
// then compiled and the expression can be resolved to a constant
break;
default:
break;
}
What you can do if you still want to use a switch() with ranged case statements is to provide some mechanism to fold the expression into one or more specific constant values.
So in a simple, trivial example you could do something like the following. This is a trivial case to show the technique which ends up making the logic of the simple if statements opaque. This technique can be useful for complex decisions and classification that can be folded into a simple set of constants.
int foldit (int iValue)
{
if (iValue < 5000) return 0;
else if (iValue < 10000) return 1;
else if (ivalue < 20000) return 2;
else return 9999; // triggers the default part of the switch
}
switch (foldit(iValue)) {
case 0:
// do what is needed for up to but not including 5000
break;
case 1:
// do what is needed for 5000 up to but not including 10000
break;
case 2:
// do what is needed for 10000 up to but not including 20000
break;
default:
// handle anything else
break;
}
Where the fold approach can be helpful is when you have several different results perhaps using a filter to try to classify a data item.
#define type1 0x00001
#define type2 0x00002
#define type3 0x00004
#define type4 0x00008
struct datatype {
int iVal;
int jVal;
};
unsigned long is_a_type1(struct datatype * thing)
{
unsigned long retVal = 0; // initialize to not a type1, set to type1 if turns out to be
// do checks for the type and if so set retVal to type1 if it matches
return retVal;
}
unsigned long is_a_type2(struct datatype * thing)
{
unsigned long retVal = 0; // initialize to not a type2, set to type2 if turns out to be
// do checks for the type and if so set retVal to type2 if it matches
return retVal;
}
unsigned long is_a_type3(struct datatype * thing)
{
unsigned long retVal = 0; // initialize to not a type3, set to type3 if turns out to be
// do checks for the type and if so set retVal to type3 if it matches
return retVal;
}
unsigned long is_a_type4(struct datatype * thing)
{
unsigned long retVal = 0; // initialize to not a type4, set to type4 if turns out to be
// do checks for the type and if so set retVal to type4 if it matches
return retVal;
}
unsigned long classify (struct datatype *thing)
{
unsigned long ulTestResult = 0;
// test to see if this is a type1 thing
ulTestResult |= is_a_type1(thing);
// test to see if this is a type2 thing
ulTestResult |= is_a_type2(thing);
// test to see if this is a type3 thing
ulTestResult |= is_a_type3(thing);
// test to see if this is a type4 thing
ulTestResult |= is_a_type4(thing);
return ulTestResult;
}
int main ()
{
struct datatype myThing;
// other source code then
switch (classify(&myThing)) {
case type1 | type2 | type3:
// do stuff if this is a type1, type2, and type3 but not type4
// that is classify() determined that myThing matched all three types.
break;
case type1:
// do stuff if type1 which includes stuff you do for type2 as well under
// special values of myThing.
if (myThing.iVal < 50) {
case type2:
// at this point we have type2 case stuff that we do. Code above is skipped
// and the switch () will jump straight to here if classify() is type2.
//
// Also stuff we do if type1 and myThing.iVal < 50
// in other words this code is execute if classify(&myThing) is type2 or
// if classify(&myThink) is type1 and there is a special processing for myThing.iVal < 50
break; // if classify() type2 or if classify() type1 and myThing.ival < 50
}
// do stuff if only type1 and myThing.iVal >= 50
break;
case type2 | type3:
// do stuff if type2 and type3 matched but none of the others.
break;
default:
// any other case
break;
}
return 0;
}
Switch statements in c can only operate on a constant expression, the case statements cannot include dynamic comparisons.
Example of something which is, and is not, a "Constant Expression" in C?
For something this simple an if/else structure could be clearer and simpler, depending on the compiler your case statement may be translated into a series of branching comparison statements anyways.

PIC16f877a switch not reading correctly

I am having a problem with a switch case when using the UART functions. I receive data and store it into the eeprom. I think call a switch statement to see what was sent. I read the eeprom and the information is right but I am just not able to read the right one. It always comes base as an error (default case). I am using Hi-tech C compiler.
unsigned char tempVal;
tempVal = eeprom_read(cmdByteAddr);
switch(tempVal){
//Get temperature
case 30:
writeByte('T');
break;
//Get temp high
case 31:
writeByte('T');
writeByte('H');
break;
//Get temp low
case 32:
writeByte('T');
writeByte('L');
break;
//Get humidity
case 41:
writeByte('H');
break;
//Get humidity high
case 42:
writeByte('H');
writeByte('H');
break;
//Get humidity low
case 43:
writeByte('H');
writeByte('L');
break;
//Error
default:
writeByte('E');
writeByte(eeprom_read(cmdByteAddr));
break;
}
The value returned from eeprom_read() is not one of your cases. The switch() is working correctly. Adjust code to present a more meaningful error using the same switch variable and not another call to eeprom_read().
default:
writeByte('E');
writeByte(tempVal);
break; // Not sure why you want `break` here.
If you still get unsatisfactory results, try unsigned tempVal. Sometimes a compiler get confused, although it should not, on sub-int sized data. You may need to writeUnsigned(tempVal) or its equivalent.
You may want to print cmdByteAddr also. Maybe it is outside the EE range.

Why was the switch statement designed to need a break?

Given a simple switch statement
switch (int)
{
case 1 :
{
printf("1\n");
break;
}
case 2 :
{
printf("2\n");
}
case 3 :
{
printf("3\n");
}
}
The absence of a break statement in case 2, implies that execution will continue inside the code for case 3.
This is not an accident; it was designed that way. Why was this decisions made? What benefit does this provide vs. having an automatic break semantic for the blocks? What was the rationale?
Many answers seem to focus on the ability to fall through as the reason for requiring the break statement.
I believe it was simply a mistake, due largely because when C was designed there was not nearly as much experience with how these constructs would be used.
Peter Van der Linden makes the case in his book "Expert C Programming":
We analyzed the Sun C compiler sources
to see how often the default fall
through was used. The Sun ANSI C
compiler front end has 244 switch
statements, each of which has an
average of seven cases. Fall through
occurs in just 3% of all these cases.
In other words, the normal switch
behavior is wrong 97% of the time.
It's not just in a compiler - on the
contrary, where fall through was used
in this analysis it was often for
situations that occur more frequently
in a compiler than in other software,
for instance, when compiling operators
that can have either one or two
operands:
switch (operator->num_of_operands) {
case 2: process_operand( operator->operand_2);
/* FALLTHRU */
case 1: process_operand( operator->operand_1);
break;
}
Case fall through is so widely
recognized as a defect that there's
even a special comment convention,
shown above, that tells lint "this is
really one of those 3% of cases where
fall through was desired."
I think it was a good idea for C# to require an explicit jump statement at the end of each case block (while still allowing multiple case labels to be stacked - as long as there's only a single block of statements). In C# you can still have one case fall through to another - you just have to make the fall thru explicit by jumping to the next case using a goto.
It's too bad Java didn't take the opportunity to break from the C semantics.
In a lot of ways c is just a clean interface to standard assembly idioms. When writing jump table driven flow control, the programmer has the choice of falling through or jumping out of the "control structure", and a jump out requires an explicit instruction.
So, c does the same thing...
To implement Duff's device, obviously:
dsend(to, from, count)
char *to, *from;
int count;
{
int n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
}
If cases were designed to break implicitly then you couldn't have fallthrough.
case 0:
case 1:
case 2:
// all do the same thing.
break;
case 3:
case 4:
// do something different.
break;
default:
// something else entirely.
If the switch was designed to break out implicitly after every case you wouldn't have a choice about it. The switch-case structure was designed the way it is to be more flexible.
The case statements in a switch statements are simply labels.
When you switch on a value, the switch statement essentially does a goto to the label with the matching value.
This means that the break is necessary to avoid passing through to the code under the next label.
As for the reason why it was implemented this way - the fall-through nature of a switch statement can be useful in some scenarios. For example:
case optionA:
// optionA needs to do its own thing, and also B's thing.
// Fall-through to optionB afterwards.
// Its behaviour is a superset of B's.
case optionB:
// optionB needs to do its own thing
// Its behaviour is a subset of A's.
break;
case optionC:
// optionC is quite independent so it does its own thing.
break;
To allow things like:
switch(foo) {
case 1:
/* stuff for case 1 only */
if (0) {
case 2:
/* stuff for case 2 only */
}
/* stuff for cases 1 and 2 */
case 3:
/* stuff for cases 1, 2, and 3 */
}
Think of the case keyword as a goto label and it comes a lot more naturally.
It eliminates code duplication when several cases need to execute the same code (or the same code in sequence).
Since on the assembly language level it doesn't care whether you break between each one or not there is zero overhead for fall through cases anyways, so why not allow them since they offer significant advantages in certain cases.
I happened to run in to a case of assigning values in vectors to structs: it had to be done in such a manner that if the data vector was shorter than the number of data members in the struct, the rest of the members would remain in their default value. In that case omitting break was quite useful.
switch (nShorts)
{
case 4: frame.leadV1 = shortArray[3];
case 3: frame.leadIII = shortArray[2];
case 2: frame.leadII = shortArray[1];
case 1: frame.leadI = shortArray[0]; break;
default: TS_ASSERT(false);
}
As many here have specified, it's to allow a single block of code to work for multiple cases. This should be a more common occurrence for your switch statements than the "block of code per case" you specify in your example.
If you have a block of code per case without fall-through, perhaps you should consider using an if-elseif-else block, as that would seem more appropriate.

Resources