#i confuse about it

31 messages · Page 1 of 1 (latest)

stable carbon
#

Explain the use of if and switch statements in program flow control.

cosmic templeBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

dusty ice
#

In C language, if and switch statements are used to control program flow based on certain conditions.

sacred monolith
#

A switch() is like a chained sequence of if()..else.
You can only compare between the same integer variable and compile-time constant values.

Example:

#define red   0xff0000;
#define green 0x00ff00;
#define blue  0x0000ff;

switch (color)
{
  case red:
    // code handling red here
    break;
  case green:
    // code handling green here
    break;
  case blue:
    // code handling red here
    break;
}

You cannot use switch() to compare two variables

int var1 = calcV1();
int var2 = calcV2();

switch (var1)
{
  case var2:  // compiler error, var2 not a compile-time constant
   ...
}

Nor can you use switch() for non-integer comparisons

char input[100];
fgets(input, 100, stdin);

switch (input)
{
  case "add":  // compiler error, comparing non-integer values
    break;
}

When you cannot use switch() then you should just fall back to repeated if()...else.
And even with if()..else you cannot directly compare strings. You should combine if() with strcmp() or variant functions.

patent zinc
#

;compile

#include <stdio.h>

int main()
{
    char c = 'a';
    
    switch (c)
    {
        case 'a':
            printf("Hello World!");
            break;
        default:
            break;
    }

    return 0;
}
supple bronzeBOT
#
Program Output
Hello World!
patent zinc
#

;compile

#include <stdio.h>

int main()
{
    char c = 'b';
    
    switch (c)
    {
        case 'a':
            printf("Hello World!");
            break;
        default:
            break;
    }

    return 0;
}
supple bronzeBOT
#
Compilation successful

No output.

patent zinc
#

🤷‍♂️

sacred monolith
#

A character is an integer type.
It ranges from -128 to 127 or from 0 to 255 if unsigned.

patent zinc
#

sure i guess but telling a beginner you cant use switch with non-integers sounds a lot like saying they cant do it with anything other than an int

#

im certain the OP doesnt know the meaning of what you just said

#

but fair enough

patent zinc
#

p.s. cant switch array of chars but you can still use switch to process it by switching chars inside a loop

#

;compile

#include <stdio.h>

int main() {
    char* s = "switch";

    for (int i = 0; s[i] != '\0'; i++) {
        switch (s[i]) {
            case 's':
                printf("s\n");
                break;
            case 'w':
                printf("w\n");
                break;
            case 'i':
                printf("i\n");
                break;
            case 't':
                printf("t\n");
                break;
            case 'c':
                printf("c\n");
                break;
            case 'h':
                printf("h\n");
                break;
            default:
                break;
        }
    }

    return 0;
}
supple bronzeBOT
#
Program Output
s
w
i
t
c
h
frank harbor
#

... another thing of note is that switch statements do not exist to make an if-else tree syntactically nicer.

#

it does not achieve that. In fact it's much worse. A lot of C++ tutorials frame switches this way. "Oh look it's shorter and neater." No, it is not shorter, it is not neater. That isn't why it's there.

#

the reason switch statements exist is basically because..,... they're a lightweight abstraction from a common construct in machine language called a jump table, which basically let you choose which code to run without even checking the conditions. (huge speedup)

#

so if you have like ```c
switch(a)
{
case 1:
code block a
case 2:
code block b
case 3:
code block c
}

.... then its probably going to create a table in memory like.... ```
table = [
  [address of code block a],
  [address of code block b],
  [address of code block c]
]
#

and then what its going to do is basically get the correct address for a at table[a-1]

#

and jump to it and start executing code from there. So... it can choose the correct code to run without evaluating each case as in an if-else tree.

frank harbor
#

;asm ```c
#include <stdio.h>
int main(void)
{
int c = getchar();

    switch(c)
    {
            case 'a':
                    printf("It's a\n");
                    break;
            case 'b':
                    printf("It's b\n");
                    break;
            case 'c':
                    printf("It's c\n");
                    break;
            case 'd':
                    printf("It's d\n");
                    break;
            case 'e':
                    printf("It's e\n");
                    break;
            case 'f':
                    printf("It's f\n");
                    break;
            case 'g':
                    printf("It's g\n");
                    break;
            default:
                    printf("Uh oh D:\n");
    }
    return 0;

}

supple bronzeBOT
#
Assembly Output
.LC0:
  .string "It's a"
.LC1:
  .string "It's b"
.LC2:
  .string "It's c"
.LC3:
  .string "It's d"
.LC4:
  .string "It's e"
.LC5:
  .string "It's f"
.LC6:
  .string "It's g"
.LC7:
  .string "Uh oh D:"
main:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  call getchar
  mov DWORD PTR [rbp-4], eax
  mov eax, DWORD PTR [rbp-4]
  sub eax, 97
  cmp eax, 6
  ja .L2
  mov eax, eax
  mov rax, QWORD PTR .L4[0+rax*8]
  jmp rax
.L4:
  .quad .L10
  .quad .L9
  .quad .L8
  .quad .L7
  .quad .L6
  .quad .L5
  .quad .L3
.L10:
  mov edi, OFFSET FLAT:.LC0
  call puts
  jmp .L11
.L9:
  mov edi, OFFSET FLAT:.LC1
  call puts
  jmp .L11
.L8:
  mov edi, OFFSET FLAT:.LC2
  call puts
  jmp .L11
.L7:
  mov edi, OFFSET FLAT:.LC3
  call puts
  jmp .L11
.L6:
  mov edi, OFFSET FLAT:.LC4
  call puts
  jmp .L11
.L5:
  mov edi, OFFSET FLAT:.LC5
  call puts
  jmp .L11
.L3:
  mov edi, OFFSET FLAT:.LC6
  call puts
  jmp .L11
.L2:
  mov edi, OFFSET FLAT:.LC7
  call puts
.L11:
  mov eax, 0
  leave
  ret

frank harbor
#
.L4:
  .quad .L10
  .quad .L9
  .quad .L8
  .quad .L7
  .quad .L6
  .quad .L5
  .quad .L3
#

this is the "jump table" i was talking about

#

from sub eax, 97 and mov rax, QWORD PTR .L4[0+rax*8] and jmp rax ..... we can see that its basically converting the entered char into an offset, converting the offset into an actual address using the jump table, and then jumping to the address.

frank harbor
#

Another thing to note is all these jmp .L11 in the code blocks calling puts

#

...... thats basically the break;.

#

If you were to get rid of one of the breaks in the switch statement, it would probably get rid of one of the jmp .L11's to allow it to follow through.