Default case in a switch condition - c

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

Related

Skip input buffer in c?

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.

Is GCC's -Wmaybe-uninitialized generating a spurious warning with -O1 for a switch statement based on an enum?

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

How to do an explicit fall-through in C

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"

gcc -Wall -Wuninitialized is not throwing warning for uninitialized variable

gcc version - gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
Compiling below code with -Wall -Wuninitialized is throwing warning as expected
warning: ‘test’ is used uninitialized in this function [-Wuninitialized]
#include<stdio.h>
#include<stdlib.h>
void check (int test )
{
printf("%d",test);
}
int
main()
{
int test;
check(test);
return 0;
}
But compiling below code with -Wall -Wuninitialized is not throwing warning
#include<stdio.h>
#include<stdlib.h>
void check (int test )
{
printf("%d",test);
}
int
main()
{
int test;
int condition = 0;
if(condition == 27)
test = 10;
check(test);
return 0;
}
Shouldn't it throw warning?. is it anyway related to compiler optimization?
What an user understands as a false positive may be different for the particular
user. Some users are interested in cases that are hidden because of
actions of the optimizers combined with the current environment.
However, many users aren't, since that case is hidden because it
cannot arise in the compiled code. The canonical example is (MM05):
int x;
if (f ())
x = 3;
return x;
where 'f' always return non-zero for the current environment, and
thus, it may be optimised away. Here, a group of users would like to
get an uninitialized warning since 'f' may return zero when compiled
elsewhere. Yet, other group of users would consider spurious a warning
about a situation that cannot arise in the executable being compiled.
https://gcc.gnu.org/wiki/Better_Uninitialized_Warnings#Proposal
EDIT: MMO5 is already fixed
https://gcc.gnu.org/wiki/Better_Uninitialized_Warnings#MM05
Yes, gcc is not warning you because the code is optimized away. Some people think this is the right thing, because it might be that way by a compile time configuration value. Others think it's the wrong thing, because it hides possible mistakes.
You are not the first to notice this problem with GCC. There's a whole proposal about it.
clang with -Wall detects the problem and even suggests a fix.
$ make
cc -Wall -g test.c -o test
test.c:15:7: warning: variable 'test' is used uninitialized whenever 'if' condition is false
[-Wsometimes-uninitialized]
if(condition == 27)
^~~~~~~~~~~~~~~
test.c:18:10: note: uninitialized use occurs here
check(test);
^~~~
test.c:15:4: note: remove the 'if' if its condition is always true
if(condition == 27)
^~~~~~~~~~~~~~~~~~~
test.c:12:12: note: initialize the variable 'test' to silence this warning
int test;
^
= 0
1 warning generated.

Linux terminal - error: label at end of compound statement

I'm using x64 Ubuntu Linux via VMware Player as a virtual machine. As a part of my project, I need to install some library (fec-3.0.1). I'm new to Linux and not good at coding.
Here is the error I encounter in terminal after successful configuration:
farhat#ubuntu:~/project/fatcaps_v0.5/fec-3.0.1$ make
gcc -g -O2 -I. -Wall -c -o dotprod.o dotprod.c
dotprod.c: In function ‘freedp’:
dotprod.c:56:3: error: label at end of compound statement
default:
^
make: *** [dotprod.o] Error 1
Here is function 'freedp' content (the start line is 55):
/* Free a dot product descriptor created earlier */
void freedp(void *p){
switch(Cpu_mode){
case PORT:
default:
#ifdef __i386__
case MMX:
case SSE:
return freedp_mmx(p);
case SSE2:
return freedp_sse2(p);
#endif
#ifdef __VEC__
case ALTIVEC:
return freedp_av(p);
#endif
}
}
What should I do?
The reason why you meet the error label at end of compound statement is because the default case can not be empty, it means you must provide a break or ; empty statement.
Edited: I find some material on that topic, and I got that: https://mail.gnome.org/archives/evolution-patches/2004-April/msg00235.html, It is the problem about the compiler gcc3.4, which reports an error on default without statements, and it is warning on gcc3.3, but now, I test on gcc4.8.2, it is all right....

Resources