I'm using coroutines in C using several macros to simplify writing code. As it is known, these macros encapsulate the code inside a big switch statement, and use case __LINE__ to know where to return. The problem is that using a switch inside a coroutine will make it fail, because the case __LINE__ will belong to the inner switch, and not the outer one.
Is it possible, by passing a parameter to GCC, to "disable" nested switch support, thus ensuring that putting a switch inside another switch will return an error or, at least, a warning?
Is it possible, by passing a parameter to GCC, to "disable" nested switch support, thus ensuring that putting a switch inside another switch will return an error or, at least, a warning?
No, gcc does not have support for this.
Related
Is there a C macro, a GCC directive or pragma, to consume the next code statement following the macro, without explicitly passing it as an argument to the macro?
Something like this:
#define CONSUME_NEXT_IF(a) if (a) { (<next>) } else;
And I would use it as:
CONSUME_NEXT_IF(a) stmt1;
And expect it to expand to:
if (a) stmt1;
else;
I am using an if statement here just as an example. The conditional statement isn't the point, rather the ability to consume stmt1 by the macro without actually passing it as an argument.
#define CONSUME_NEXT_IF(a) if (!(a)) {} else
will achieve the effect of only executing the "next statement" (between use of the macro and next ;) if a is true (or non-zero). If you have suitable constraints on what type of expression a is, you might be able to remove the () on (a).
Personally, although you've explained in comments that you want a similar effect to annotations, I consider this will introduce more maintenance concerns - including code obfuscation - than it alleviates. Particularly if it interacts with other macros being used in a or stmt1.
And, of course, it would be necessary to modify your "large code base" to use the macro.
This also leaves dead code in your executable - it doesn't stop code for stmt1 being emitted to the executable (unless a has a fixed compile-time value, and your compiler has capability to detect and optimise code in such circumstances). Therefore such a construct will mean you cannot satisfy requirements of several assurance standards that require prevention of dead code.
Something about switch-case statement is very unclear for me. First of all I could understand the case part as an if statement, but what dose switch do itself? I mean when we pass argument to switch, what happens there?
c=getchar();
switch(c)
2: Why there is no need to put ; after switch? What kind of the function is it?
3: How compilers implement switch-case statement at the first time? (just C or use assembly)
4: We can't use switch-case like this:
switch(string)
{
case "aaaa":
...
case "bbbb":
...
we use if-strcmp instead. Is it possible to create switch-case like statement for string condition? I see some library like getopt use struct to handle command line string arguments:
{"help",...,'h'},
{"version",...,'v'}
...
but I want to use string directly.
first of all I could understand "case" part as a "if" statement, but what dose switch do itself? I mean when we pass argument to switch, what happens there?
In case, there's always a constant. You need to "compare" something with this constant. And switch(a) means - "compare a with:" and it "compares" it to each case statement.
2: why there is no need to put ";" after switch? what kind of the function is it?
It's not a function. You're not calling switch function, you're just starting to write a switch statement.
3: how compilers implement switch-case statement at the first time? (just C or use assembly)
That's platform specific. Sometimes, it's implemented using jumps (asm) and offsets.
4: we can't use switch-case like this:
Because switch works only with integral types (that is int, enum, char, etc. and not double, strings, etc.)
The switch statement begins the scope of the cases. Scopes in C/C++ are always bound by curly braces ( {} ), specifying the scope of local variables (on the stack) which is used to hold the switch parameter. It hence doesn't need a ; since it is grammatically much like a while loop.
Compilers implement switchs as direct jump in assembly. This is what makes them really more efficient than ifs (which are mostly compiled as different comparisons in assembly). This is also the reason why you can't use a switch on text. The value of a char* is only a pointer, hence cannot be used to correctly identify the target section to execute.
To use strings in switch case() in c what you can do is, to store the possible strings of switch in a string as
char * switchstr[]={"abc", "def", "ghi"};
then search for the input string in the switchstr[] and use the index of matching string as switch case parameter.
And to know why strings are not supported in switch case read this answer. IT has discussion about why string cant be used directly in switch statement in C/C++.
And also switch case checks for equality and we know in C it is not possible to check the equality of string directly by using = sign, instead we need to use strcmp() function.
first of all I could understand "case" part as a "if" statement, but what dose switch do itself?
The switch part sets the expression that is used to compare with the values in the associated case labels.
2: why there is no need to put ";" after switch? what kind of the function is it?
It is not a function; switch is a language keyword that is part of the switch statement (i.e. the whole switch/case construct). It is not a function just because it uses parentheses any more than while(...) or if(...) are functions.
3: how compilers implement switch-case statement at the first time? (just C or use assembly)
That is up to the compiler. How things are implemented is generally not within the purview of a language standard, only (as precisely as possible) what should happen.
In practice, a switch statements tend to be implemented with branches if there are only a few cases, and with a jump table if there are many.
4: we can't use switch-case [with strings]
Because C defines the switch statement as working with integral types. A string is not an integral type. To provide the kind of functionality you envisage would require adding (at least) “content equality” testing for strings to the core C language. To do this consistently in a way that does not break existing code is probably impossible and contrary to the “minimalist” philosophy of C.
I'm writing a bytecode interpreter that can either use computed gotos or a normal switch for the main instruction dispatching loop. The key bits are wrapped up in a couple of macros that can either be defined to use computed gotos or not.
I'd like to decide which mode to use by default based on whether or not the compiler supports computed gotos. Does anyone know how to determine that? As far as I can tell, they work on GCC and Clang, but I don't want to just hardcode a couple of random compiler names.
If you're using a tool such as autoconf, the following feature test have been useful for me:
AC_MSG_CHECKING([if ${CC-gcc} supports computed gotos])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[],
[[
void *my_label_ptr = &&my_label; /* GCC syntax */
goto *my_label_ptr;
return 1;
my_label:
return 0;
]])],
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_COMPUTED_GOTOS, 1,
[Define to 1 if the compiler supports computed gotos])],
[AC_MSG_RESULT(no)])
It will define the macro HAVE_COMPUTED_GOTOS if the compiler supports the GCC syntax.
Assume I have a function C.
uint8_t readPin(uint8_t);
uint8_t readPin(uint8_t pin_num)
{
switch pin_num
{
case 0:
return(PORTAbits.RA3);
break;
case 1:
...and so on
}
}
I want to call the pin using a more human readable name (that can be remapped). For example, I want to be able to write:
openDoor();
to call
readPin(2);
I tried using
#define openDoor() readPin(2)
but that doesn't work because of the parentheses. Does anyone have a suggestion on how best to do this? I can't just rename the readPin function because I want to have more than 1 different aliases for it depending on which header file I include.
#define openDoor() readPin(2)
What you have is fine. Macros can have argument lists, even empty argument lists, so this will do what you want.
However, I caution against using the preprocessor like this. It's best to avoid using the preprocessor, particularly when the language can do the exact same thing. Debuggers can't see preprocessor macros, for one thing.
void openDoor()
{
readPin(2);
}
#define openDoor() readPin(2)
It should work fine.
Because , #defineis used just to replace wherever it finds the replacing token with the appropriate value defined for it before compiling that is preprocessing.
So, if you write openDoor() it will replace with readPin(2) before compilation
In a C switch-case flow control, it's required to put curly braces { } after a case if variables are being defined in that block.
Is it bad practice to put curly braces after every case, regardless of variable declaration?
For example:
switch(i) {
case 1: {
int j = 4;
...code...
} break;
case 2: { //No variable being declared! Brace OK?
...code...
} break;
}
It's certainly not invalid to use braces in every case block, and it's not necessarily bad style either. If you have some case blocks with braces due to variable declarations, adding braces to the others can make the coding style more consistent.
That being said, it's probably not a good idea to declare variables inside case blocks in straight C. While that might be allowed by your compiler, there's probably a cleaner solution. Mutually-exclusive case blocks may be able to share several common temporary variables, or you may find that your case blocks would work better as helper functions.
Braces may be used in every case statement without any speed penalty, due to the way compilers optimize code. So it's just the style and the preference of the coder.
The most preferred usage is not using braces, though the usage of them in every case during an active development may be found easier to make some additions on the code every now and then.
It's just the easthetics; because a 'case' statement doesn't need only a single command, but will walk through the code as it works as a label. So blocks are not needed, and are not invalid.
In 'case's with variables; braces are used just-in-case, to create contexts for variables, and it makes big sense to use them. Some compilers on different platforms show different behaviours if they are not included.
I consider it bad style to use braces in each case. Cases are labels in C, akin to goto labels. And in the current C language, you're free to declare variables in each case (or anywhere you like) without introducing new blocks, though some people (myself included) also consider that bad style.
Generally it is bad practice jump over the initialization of a variable, be it with goto or switch. This is what happens when you don't have the the blocks per case.
There is even a case in C99 where jumping over the initialization is illegal, namely variable length arrays. They must be "constructed" similarly as non-PODs in C++, their initialization is necessary for the access of the variable later. So in this case you must use the block statement.
Just to add a minor point many editors & IDEs allow blocks to be collapsed and/or auto indented and several allow you to jump to the matching brace - I personally don't know of any that allow you to jump from a break to the matching case statement.
When debugging, or re-factoring, other peoples, (or even your own after a few months), code that contains complex case statements the ability to both collapse sections of the code and to jump to matching cases is invaluable, especially if the code contains indentation variations.
That said it is almost always good advice to avoid complex case statements like the plague.