The newer versions of gcc offer the Wimplicit-fallthrough, which is great to have for most switch statements. However, I have one switch statement where I want to allow fall throughs from all case-statements.
Is there a way to do an explicit fall through? I'd prefer to avoid having to compile with Wno-implicit-fallthrough for this file.
EDIT: I'm looking for a way to make the fall through explicit (if it's possible), not to turn off the warning via a compiler switch or pragma.
Use __attribute__ ((fallthrough))
switch (condition) {
case 1:
printf("1 ");
__attribute__ ((fallthrough));
case 2:
printf("2 ");
__attribute__ ((fallthrough));
case 3:
printf("3\n");
break;
}
GCC fallghrough magic comments
You should not use this if you can help it, it is insane, but good to know about:
int main(int argc, char **argv) {
(void)argv;
switch (argc) {
case 0:
argc = 1;
// fall through
case 1:
argc = 2;
};
}
prevents the warning on GCC 7.4.0 with:
gcc -Wall -Wextra main.c
man gcc describes how different comments may or not be recognized depending on the value of:
-Wimplicit-fallthrough=n
C++17 [[fallthrough]] attribute
C++17 got a standardized syntax for this: GCC 7, -Wimplicit-fallthrough warnings, and portable way to clear them?
You should be able to use GCC diagnostic pragmas to disable that particular warning for your source file or some portion of a source file. Try putting this at the top of your file:
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
Related
I am making a small console game and want to allow instant input and output for the player so that they don't have to hit enter after each move. I understand there are already a few solutions that can be found online, most prominently ncurses (I'm on linux), but I have not been able to get anything to work. When I input the code below, I get the message:
main.cpp:(.text+0x39c): undefined reference to `initscr'
main.cpp:(.text+0x3a3): undefined reference to `stdscr'
main.cpp:(.text+0x3ac): undefined reference to `wgetch'
main.cpp:(.text+0x3b4): undefined reference to `endwin'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I understand skipping the input buffer is not standard in C, but any ways around this would be greatly appreciated. I can make the code work by just using key = getchar(); but as aforementioned, I want to skip the necessary enter key.
void move(int key){
initscr();
key = getch();
switch(key){
case 'w': if (playery > 1){y--;}
break;
case 's': if (playery < height - 1){y++;}
break;
case 'a': if(playerx > 1){x--;}
break;
case 'd': if(playerx < width - 1){x++;}
break;
default: grid[x][y] = 'x';
break;
}
endwin();
}
You need to link with ncurses to make it work. When you include curses.h or ncurses.h, it includes just the definitions. The actual code is separated, so you have to tell your compiler to add the code to your program.
Compiling with clang
Use this when compiling C++:
clang++ main.cpp -lncurses
Use this when compiling C:
clang main.c -lncurses
Never use clang with C++ or clang++ with C. It creates a huge mess.
Compiling with GNU/gcc
Use this when compiling C++:
g++ main.cpp -lncurses
Use this when compiling C:
gcc main.c -lncurses
Again, do not interchange those.
You say you use C, but you have main.cpp, which implies you are using C++. Rename your file to main.c or edit your question.
As noted in comments, ncurses already has a function named move. You should rename your function.
I have a piece of code of the following form:
typedef enum {A=1,B} EnumType;
int foo (EnumType x)
{
int r;
switch (x) {
case A:
r = 1;
break;
case B:
r = 2;
break;
/*
default:
r = -1;
break;
*/
}
return r;
}
I compile with GCC 6.3.0 and receive a warning:
$ gcc --version
gcc (MacPorts gcc6 6.3.0_2) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -c -Wall -O1 test.c
test.c: In function 'foo':
test.c:20:10: warning: 'r' may be used uninitialized in this function [-Wmaybe-uninitialized]
return r;
^
The code seems safe to me, and indeed there is some discussion of GCC producing false positives with this warning.
Is this a spurious warning?
More relevant information:
Adding the commented-out default: block resolves the warning
The warning does not appear with -O0
This warning is entirely correct, because an enum type doesn't restrict the possible values to the members defined in this enum -- it can instead hold any value of the underlying integer type. So without a default branch in your switch, you could indeed use r uninitialized with the code you show.
I can reproduce the warning missing with gcc and -O0 with the exact code shown in the question, so this looks to me like a bug in gcc. The warning should be given regardless of the optimization level.
It is easy to figure out: there are possible program paths where r will be returned uninitialised. So you got the warning. Enum is just the int so you have a lots possible cases.
Enums are not checked runtime against the values.
About the second part of the question. It is intentional as any level of optimisation may (and in this case will remove the code if the values of the enum type are illegal - compiler assumes that no other values are possible)
https://godbolt.org/g/S9XE3d
This case is most interesting:
https://godbolt.org/g/TDUhN7
You may think that you have checked against illegal values. But the compiler has stripped the code out :)
BTW - interesting why my answer was downvoted
Code sample:
int main(int argc, char **argv)
{
switch(argc)
{
case 0:
argc = 5;
__attribute__((fallthrough));
case 1:
break;
}
}
Using gcc 6.3.0, with -std=c11 only, this code gives a warning:
<source>: In function 'main':
7 : <source>:7:3: warning: empty declaration
__attribute__((fallthrough));
^~~~~~~~~~~~~
What is the correct way to use this without eliciting a warning?
As previously answered, __attribute__ ((fallthrough)) was introduced in GCC 7.
To maintain backward compatibility and clear the fall through warning for both Clang and GCC, you can use the /* fall through */ marker comment.
Applied to your code sample:
int main(int argc, char **argv)
{
switch(argc)
{
case 0:
argc = 5;
/* fall through */
case 1:
break;
}
return 0;
}
Tried to comment previous, but did not have 50 reputation.
So, my experiences:
1) the feature is since gcc 7, so using attribute on older
compilers will give warning. therefore I currently use:
#if defined(__GNUC__) && __GNUC__ >= 7
#define FALL_THROUGH __attribute__ ((fallthrough))
#else
#define FALL_THROUGH ((void)0)
#endif /* __GNUC__ >= 7 */
and then I use FALL_THROUGH; in code
(Some day I figure out what is needed for clang, but not today)
2) I spent considerable time to try to get the gcc marker comment to work, but nothing I tried worked! Some comment somewere suggested that in order for that to work one has to add -C to
gcc arguments (meaning comments will be passed to cc1). Sure gcc 7 documentation doesn't mention anything about this requirement...
You can also try the code below, because only this one works for me on Android:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
// your code
#pragma GCC diagnostic pop
I got the following error message while compiling the C code:
error: 'for' loop initial declarations are only allowed in C99 mode
note: use option -std=c99 or -std=gnu99 to compile your code
What does it mean?
How to fix it?
You have done this:
for (int i=0;i<10;i++) {
And you need to change it to this:
int i;
for (i=0;i<10;i++) {
Or, as the error says,
use option -std=c99 or -std=gnu99 to compile your code.
Update copied from Ryan Fox's answer:
gcc -std=c99 foo.c -o foo
Or, if you're using a standard makefile, add it to the CFLAGS variable.
You'll still need C99 if you want to mix statements and variable declarations. As other answers and the error message itself say, add -std=c99 to the command-line when you compile to enable C99 features [1].
But you have always been allowed to write a compound statement (a "block", IOW, but the standard never uses this word!) in place of a single statement.
#include<stdio.h>
int main() {
int i = 5;
{ /* new block, new declarations. */
int i;
for (i=0;i<10;i++){
}
}
printf("%d\n", i); /* prints "5\n" */
}
This is legal in K&R, C90 (aka C89, it's the same thing), and C99.
Enabling C99 mode gets you lots of cool stuff, but it also disables some other cool stuff that gcc allows by default, like anonymous structures and unions within structures and unions.
-std=gnu99 probably enables "all the goodies", but I caution you to avoid doing this. It will make unnecessary difficulty if you (or others) wish to port the code. I'd probably have a windows version of my pet project, ported for free by somebody, had I not done this very thing. It ties you gcc. You don't want to be tied. That's the whole bloody point of standards.
The other answers give you a work around to deal with GCC's default mode. If you'd like to use C99, (which I do recommend in general) then you have to add that compiler flag:
gcc -std=c99 foo.c -o foo
Or, if you're using a standard makefile, add it to the CFLAGS variable.
It means you can't declare variables in for statement.
You should do:
int i ;
for( i = 0 ; i < len ; i++ )
What you are probably doing
for( int i = 0 ; i < len ; i++ )
I have this code:
#include<stdio.h>
int main()
{
int a=10;
switch(a)
{
case '1':
printf("ONE\n");
break;
case '2':
printf("TWO\n");
break;
defalut:
printf("NONE\n");
}
return 0;
}
The program doesn't print anything, not even NONE. I figured out that default had a typo defalut!
I want to know why this syntax error is not detected by the compiler.
defalut is just a label in your program that you can jump to with goto. Having an editor that highlights keywords could have made this error easier to spot.
I should also note that your program may have some logic errors. The character '1' is not the same as 1, and the same with '2' and 2.
That's not a syntax error. defalut is a valid label, and it could be the target of a goto.
tip: if you are using gcc, add the option -pedantic. it will warn you for unused labels:
$ gcc -ansi -Wall -pedantic test.c -o test
test.c: In function ‘main’:
test.c:14:10: warning: label ‘defalut’ defined but not used