Skip to content

C Programming From Basics to Mastery

Switch Statement in C

Using floating-point numbers in switch statements in C is not recommended (and in many cases not even possible) due to several reasons:

1. Precision Issues

Floating-point numbers are stored in binary with finite precision, which can lead to subtle inaccuracies. This means that even if two floating-point numbers look equal in source code, they might not match exactly in memory due to rounding errors.

For example:

C
float a = 0.1;
float b = 0.1 * 3 / 3;
if (a == b) {
  printf("a == b\n"); // this will work
}

In a switch statement, the case labels must have exact matches, and such precision issues make it unreliable to use floating-point numbers.

C
float a = 0.1;
float b = 0.1 * 3 / 3;
switch(b) { // error: Statement requires expression of integer type ('float' invalid)
  case 0.1: // error: Integer constant expression must have integer type, not 'double'
    printf("\n");
    break;
}

Attempting to write a switch statement with a float would result in the following errors:


2. Standard Restriction

The C standard (ISO C99 and later) specifies that the expression in a switch statement must evaluate to an integer or an enumerated type. Floating-point numbers are explicitly disallowed. The syntax is defined this way to ensure predictable and efficient behavior.

printf Format Specifiers

This table is listing the common printf format specifiers for various data types in C language

Data TypeFormat SpecifierDescriptionExample Usage
int%d or %iSigned decimal integerprintf("%d", 42);
unsigned int%uUnsigned decimal integerprintf("%u", 42);
float%fDecimal floating-pointprintf("%f", 3.14);
double%lfDouble floating-pointprintf("%lf", 3.14);
char%cSingle characterprintf("%c", 'A');
char* (string)%sString of charactersprintf("%s", "hello");
short%hdShort signed integerprintf("%hd", 42);
unsigned short%huShort unsigned integerprintf("%hu", 42);
long%ld or %liLong signed integerprintf("%ld", 42L);
unsigned long%luLong unsigned integerprintf("%lu", 42UL);
long long%lld or %lliLong long signed integerprintf("%lld", 42LL);
unsigned long long%lluLong long unsigned integerprintf("%llu", 42ULL);
int (octal)%oUnsigned octal integerprintf("%o", 42);
int (hexadecimal)%x or %XUnsigned hexadecimal integer (lowercase/uppercase)printf("%x", 42);
float/double (scientific)%e or %EExponential notation (lowercase/uppercase)printf("%e", 3.14);
float/double (auto)%g or %GShortest representation of %f or %e/%Eprintf("%g", 3.14);
void* (pointer)%pPointer address (hexadecimal)printf("%p", &var);
Literal %%%Prints a percent signprintf("%%");

Notes:

  1. Precision and Width: You can modify these specifiers with width and precision, e.g., %5.2f for a float with 5 total characters and 2 after the decimal.
  2. Platform Dependence: Some specifiers (like %lf for double) may behave differently depending on the compiler or standard (e.g., C89 vs. C99).
  3. Size Modifiers: Use h (short), l (long), or ll (long long) to adjust for specific integer sizes.