Author Topic: C Programming - Refer to switch structure value inside each case statement  (Read 1307 times)

0 Members and 1 Guest are viewing this topic.

Offline Sergio

  • Contributor
  • Posts: 11
  • Country: es
Hello,
I will try to do my best explaining my question.
In a case structure like this one:
Code: [Select]
switch(Value){
    case 1:   
        OutputValue= "CaseValue" + 275;
        break;               
    case 2:     
        OutputValue= "CaseValue" + 275;
        break;             
    case 3:   
        OutputValue= "CaseValue" + 275;
        break;             
}

Would it be possible to refer to each case value inside the case statement without writing manually the value?
On the example, the three possible results would be 276, 277 and 278.
The example is very simple, but I have code where I use several times the "CaseValue" inside the statement and I repeat the structure for several Case values. So using a reference to the value would allow to copy-paste the structure without having to modify each value manually and maybe avoiding human mistakes

Thank you in advance for any help
« Last Edit: June 29, 2021, 02:41:48 pm by Sergio »
 

Offline evb149

  • Super Contributor
  • ***
  • Posts: 1924
  • Country: us
I'm not sure what you mean.

In each case statement the switch argument (Value) is the 'CaseValue' by definition.

switch(Value){
    case 1:   
        OutputValue= Value + 275; // Value=1
        break;               
    case 2:     
        OutputValue= Value + 275; // Value=2...
        break;             
    case 3:   
        OutputValue= Value + 275;
        break;             
}
 

Offline Sergio

  • Contributor
  • Posts: 11
  • Country: es
Never mind.
I realized how stupid the question is after posting it. Just use
Code: [Select]
switch(Value){
    case 1:   
        OutputValue= Value + 275;
        break;               
    case 2:     
        OutputValue= Value + 275;
        break;             
    case 3:   
        OutputValue= Value + 275;
        break;             
}

 :palm:
 

Offline evb149

  • Super Contributor
  • ***
  • Posts: 1924
  • Country: us

const uint32_t  offset_value = Value + 275U;

switch(Value){
    case 1:   
        OutputValue= offset_value;
        break;               
    case 2:     
        OutputValue= offset_value;
        break;             
    case 3:   
        OutputValue= offset_value;
        break;             
}
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 10480
Oh for %DEITY%'s sake, if the case blocks in question are actually identical use fallthrough rather than copy/pasta code!
Code: [Select]
switch(Value){
    case 1:   
    case 2:     
    case 3:   
        OutputValue= Value + 275;
        break;             

    // Other case blocks that require separate handling
}
 
The following users thanked this post: newbrain, Nominal Animal

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 10480
Finally, if you can tolerate a GCC specific departure from ANSI C, you can use case ranges:
Code: [Select]
switch(Value){
    case 1 ... 3:   
        OutputValue= Value + 275;
        break;             

    // Other case blocks that require separate handling
}
which tidies it up considerably.  See: https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html

N.B. the ellipses indicating a range should always be separated by whitespace from the range limits.

 
The following users thanked this post: georgian

Offline golden_labels

  • Frequent Contributor
  • **
  • Posts: 402
  • Country: pl
Sometimes the mot obvious is not obvious:
Code: [Select]
if (Value >= 1 && Value <= 3) {
    OutputValue = Value + 275;
}
Worth watching: Calling Bullshit — protect your friends and yourself from bullshit!
 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 1674
  • Country: es
Finally, if you can tolerate a GCC specific departure from ANSI C, you can use case ranges:
Code: [Select]
switch(Value){
    case 1 ... 3:   
        OutputValue= Value + 275;
        break;             

    // Other case blocks that require separate handling
}
which tidies it up considerably.  See: https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html

N.B. the ellipses indicating a range should always be separated by whitespace from the range limits.

Nice one! I always wondered if it could be done that way instead piling up "cases".
Hantek DSO2x1x            Drive        FAQ
Stm32 Soldering FW      Forum      Github      Donate
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 2368
  • Country: nz
  • Formerly SiFive, Samsung R&D
Finally, if you can tolerate a GCC specific departure from ANSI C, you can use case ranges:
Code: [Select]
switch(Value){
    case 1 ... 3:   
        OutputValue= Value + 275;
        break;             

    // Other case blocks that require separate handling
}
which tidies it up considerably.  See: https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html

N.B. the ellipses indicating a range should always be separated by whitespace from the range limits.

Nice one! I always wondered if it could be done that way instead piling up "cases".

Only in gcc, and compilers that try to be compatible with gcc, such as Clang.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 7315
  • Country: fr
And, if I'm using C, there's no way I would use such a non-standard feature. But that's just me.
 
The following users thanked this post: newbrain

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 10480
If its even remotely possible that you will need portability, then avoiding the use of any proprietary extensions is the *ONLY* sane thing to do.  OTOH if your code is already so closely tied to a platform for which only GCC based compilers are available that porting it will be a royal PITA, and reuse of significant portions elsewhere is unlikely, you've got very little to loose and quite a bit of clarity of expression to gain, by using one more proprietary GCC extension to ANSI/ISO C. 
 

Offline esepecesito

  • Regular Contributor
  • *
  • Posts: 62
  • Country: de
If you are writing low level C for microcontrollers, it could be that (compiler) portability is not your biggest concern.
I still do not like non standards. Because of "portability of maintainer". I would like my code to be interpreted by people that know only basic ANSI C.
My colleagues at work are always impressed because I use so few features of C++, and my code is extremely easy to understand, being typically faster as other code.
I also keep away of no POSIX extension in linux scripts.
 

Offline evb149

  • Super Contributor
  • ***
  • Posts: 1924
  • Country: us
Another possibly serious problem with using non standard (ISO C++/C) language extensions that are specific to a given
toolchain or compiler is that they may not be supported by CASE tools you'd care to use -- e.g.
1: syntax checking / auto-completing et. al. IDEs / editors
2: static analysis / linter tools

(1) is highly annoying if it causes your editor / IDE to fail to 'parse' the code properly and in that case it may either
flag errors that don't really exist or fail to find errors that do exist; those effects may not be localized to a small area of code --
e.g. if you have a non standard construct in some header file or at some point in a module it could "poison" the parsing of the entire module code subsequent to its appearance.

Actually that's also a problem if you use a more modern construct (e.g. C/C++ 17/14/11) than your editor / IDE parses then it may consider lots of code in your module as erroneously erroneous.

(2) is highly annoying since it can render your static analysis / linting useless for lots of "unrelated" code in your modules.
For this reason I consider it harmful if MCU embedded toolchains don't have some way to "stub out" MCU specific
things like macros, register names, etc. so they can be made to appear to be standard ISO C/C++ variables / symbols
e.g. "
extern "C" {
extern uint8_t * const  UART1_THR;
}

...just so that you can run an ISO C/C++ static analyzer on your MCU code and have it pass without warnings despite a lot
of MCU specific code and constructs present.




If its even remotely possible that you will need portability, then avoiding the use of any proprietary extensions is the *ONLY* sane thing to do.  OTOH if your code is already so closely tied to a platform for which only GCC based compilers are available that porting it will be a royal PITA, and reuse of significant portions elsewhere is unlikely, you've got very little to loose and quite a bit of clarity of expression to gain, by using one more proprietary GCC extension to ANSI/ISO C.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 7315
  • Country: fr
Yep, and, there's a definite difference between extensions that modify the standard behavior/syntax/... of existing language constructs, and extensions that add constructs or attributes that are simply not defined in the standard. While both are non-portable, the first category is far worse IMO.

The only extensions I ever use (for low-level stuff) are just attributes, which are not even breaking the standard, they are simply beyond its scope, and attributes will usually not make static analysis tools (at least decent and decently recent ones) go bonkers.
 
The following users thanked this post: newbrain


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf