I get error in C(Error- Unused Variable) for variable when I type in following code
int i=10;
but when I do this(break it up into two statements)
int i;
i=10;
The error Goes away
..I am using Xcode(ver-4.1)(Macosx-Lion)..
Is something wrong with xcode....
No nothing is wrong the compiler just warns you that you declared a variable and you are not using it.
It is just a warning not an error.
While nothing is wrong, You must avoid declaring variables that you do not need because they just occupy memory and add to the overhead when they are not needed in the first place.
The compiler isn't wrong, but it is missing an opportunity to print a meaningful error.
Apparently it warns if you declare a variable but never "use" it -- and assigning a vale to it qualifies as using it. The two code snippets are equivalent; the first just happens to make it a bit easier for the compiler to detect the problem.
It could issue a warning for a variable whose value is never read. And I wouldn't be surprised if it did so at a higher optimization level. (The analysis necessary for optimization is also useful for discovering this kind of problem.)
It's simply not possible for a compiler to detect all possible problems of this kind; doing so would be equivalent to solving the Halting Problem. (I think.) Which is why language standards typically don't require warnings like this, and different compilers expend different levels of effort detecting such problems.
(Actually, a compiler probably could detect all unused variable problems, but at the expense of some false positives, i.e., issuing warnings for cases where there isn't really a problem.)
UPDATE, 11 years later:
Using gcc 11.3.0 with -Wall, I get warnings on both:
$ cat a.c
int main() {
int i = 10;
}
$ gcc -Wall -c a.c
a.c: In function ‘main’:
a.c:2:9: warning: unused variable ‘i’ [-Wunused-variable]
2 | int i = 10;
| ^
$ cat b.c
int main() {
int i;
i = 10;
}
$ gcc -Wall -c b.c
b.c: In function ‘main’:
b.c:2:9: warning: variable ‘i’ set but not used [-Wunused-but-set-variable]
2 | int i;
| ^
$
But clang 8.0.1 does not warn on the second program. (XCode probably uses clang.)
The language does not require a warning, but it would certainly make sense to issue one in this case. Tests on godbolt.org indicate that clang issues a warning for the second program starting with version 13.0.0.
(void) i;
You can cast the unused variable to void to suppress the error.
Related
Consider the following C code:
#include <stdio.h>
int x = 5;
int y = x-x+10;
int z = x*0+5;
int main()
{
printf("%d\n", y);
printf("%d\n", z);
return 0;
}
The ANSI C90 standard states "All the expressions for an object that has static storage duration [...] shall be constant expressions" (6.5.7 constraint 3).
Clearly the initializers for y and z are not constant expressions. And indeed, trying to compile the above C code with clang main.c or clang -ansi main.c gives an error for this reason.
However, compiling with gcc main.c or even gcc main.c -ansi -pedantic -Wextra -Wall gives no errors at all, and runs, printing 10 and 5.
On the other hand, trying something like the following:
#include <stdio.h>
int x = 5;
int main()
{
int y[x-x+2];
printf("%lu\n", sizeof(y));
return 0;
}
gives a warning when compiled with gcc -ansi -pedantic ... or clang -ansi -pedantic ....
So gcc randomly performs the mathematically correct cancellations in order to pretend that something is a constant expression, even when asked not to (-ansi). Why is this? Is this a bug?
By the way, my gcc version is 9.4.0 and my clang version is 10.0.0-4.
Without looking, there's one simple explanation: the code that checks whether the initializer is an acceptable constant expression operates on an internal representation after a pass that does arithmetic simplification, so it never "sees" your x-x or x*0.
This probably makes the implementation of the rule in GCC simpler: it just has to ask "is this node one that represents a constant?" rather than "is this tree one that I could evaluate as a constant later on?". It also facilitates the behavior that they probably want for the later standards (see below), and a special case for -ansi would probably add an undesirable amount of code complexity.
Is it a bug? Arguably. But it's one with such a small impact that it's not especially likely to get fixed. It works correctly for valid code, and it errors correctly on "really" invalid code that could actually cause a problem. It only deviates from the standard in a fairly harmless way, and only for C90 (since the C99 and later standards say "an implementation may accept other forms of constant expressions", which gives GCC latitude to allow an expression that mentions things not on the laundry list, as long as it has a constant value).
What argument type should I use in C when calling a Fortran function that takes logical arguments, specifically with gfortran? Where is this documented for gfortran?
Here's an example program that doesn't compile without warnings:
Contents of one.f:
subroutine proc1(x)
logical x
end
Contents of main.c:
void proc1_(_Bool *x);
int main() {
_Bool x;
proc1_(&x);
return 0;
}
If I compile using GCC as follows, with LTO enabled, I get a warning about mismatching function prototypes:
gfortran -flto -c one.f
gcc -flto -c main.c
gcc -flto main.o one.o
The warning I get:
main.c:2:6: warning: type of 'proc1_' does not match original declaration [-Wlto-type-mismatch]
2 | void proc1_(_Bool *x);
| ^
one.f:2:22: note: 'proc1' was previously declared here
2 | subroutine proc1(x)
| ^
one.f:2:22: note: code may be misoptimized unless '-fno-strict-aliasing' is used
Note that enabling LTO allows the linker to verify that argument types match between prototypes. Using LTO is unfortunately not our choice. CRAN requires the submitted code to compile without these warnings with LTO enabled.
I only see problems when trying to use logical arguments. real, integer and character are all fine.
gfortran can be asked to produce C prototypes, and this is the output it gives me:
gfortran -flto -fc-prototypes-external -c one.f
void proc1_ (int_fast32_t *x);
Using int_fast32_t in the C prototype doesn't work either. No type that I tried did, neither int, nor _Bool. Usually, when there is a type mismatch between prototypes, the error message mentions what the type should be—but not in this case.
How can I find what is the correct type to use?
For real modern C-Fortran interoperability you should use the types (kinds) supplied by the iso_c_binding module and make your Fortran procedure bind(c). That way you can use logical(c_bool).
In the old style the best thing is to work with integers and pass an int and only correct from integer to logical inside Fortran. Old C did not have any bool, it was added later.
With minimal changes:
subroutine proc1(x)
use iso_c_binding
logical(c_bool) x
end
#include <stdbool.h>
void proc1_(bool *x);
int main() {
bool x;
proc1_(&x);
return 0;
}
> gfortran -flto -c one.f
> gcc -flto -c main.c
> gcc -flto main.o one.o
issues no warning on my Linux and GCC 7 and 10.
Or after further changes:
subroutine proc1(x) bind(C, name="proc1")
use iso_c_binding
logical(c_bool), value :: x
end
#include <stdbool.h>
void proc1(bool x);
int main() {
bool x;
proc1(x);
return 0;
}
The change to pass-by-value of course only when it is indeed just an input parameter.
The correct and guaranteed to be portable solution is, as explained in the answer by Vladimir F, to create a Fortran wrapper routine that uses ISO_C_BINDING. This wrapper can also take the opportunity to make a more idiomatic C interface, e.g. using the value specifier to pass scalars by value.
However, for the quick and dirty solution that works on GFortran WITHOUT LTO (and somewhat likely on other compilers, but no guarantees), see https://gcc.gnu.org/onlinedocs/gfortran/Internal-representation-of-LOGICAL-variables.html#Internal-representation-of-LOGICAL-variables . That is, you can pass a C integer variable of the appropriate size containing 1 for true and 0 for false. Appropriate size here meaning that unless you have compiled your Fortran code with -fdefault-integer-8 or such compile options, the GFortran default kind logical will be 4 bytes, so a plain C int should be good (or int32_t if you really want to be sure, though I don't think GFortran supports any targets where the C int is not 32 bits).
The reason this doesn't work with LTO is that while the above works, in the bowels of GCC the Fortran LOGICAL variables are almost the same as integers, but not quite. So in practice they are special integer variables with max value 1 and min value 0 even though they take up more space (as specified by their kind parameter). So this kind of type mismatch is likely what it complains about. Unfortunately no solution to this one, except the above correct solution via ISO_C_BINDING.
Hitting below warning with new gcc version 6.X
Warning: 'temp' may be used uninitialized in this function [-Wmaybe-uninitialized]
Code:-
int temp;
if (logcat (MSPRO_P->regs[test],
byte, &temp, test) == FALSE){
memErrorMsgHistoryVa (MSPRO_MEMP, "Invalid Data Count 0 value");
MSPRO_P->flashCmdError = TRUE;
}
gcc isn't supposed to warn about passing a pointer to an uninitialized variable to a function it doesn't know anything about (the assumption is that the function will initialize it). So I'm pretty sure that gcc knows things about logcat and the uninitialized use is detected in there. Maybe it got inlined or such.
Example:
$ cat > foo.c
static int
bar(int *a)
{
return *a + *a;
}
int
foo(void)
{
int x;
int y = bar(&x);
return x + y;
}
$ cc -Wall -c foo.c
$
Here, despite it being blindingly obvious to humans, gcc doesn't actually know what happens inside the function bar. So no warning.
Let's help gcc to understand what's going on:
$ cc -O1 -Wall -c foo.c
foo.c: In function ‘foo’:
foo.c:4:12: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
return *a + *a;
~~~^~~~
foo.c:10:6: note: ‘x’ was declared here
int x;
^
$
Just turning on optimization helped gcc to see what's going on (probably some inlining happened).
From the minimal piece of code you've shown and the warning message, where it looks like you cut out the bit that actually tells you exactly where in your code the problem happens, I conclude that the problem is in your logcat function.
temp is uninitialized after int temp;.
logcat (MSPRO_P->regs[test], byte, &temp, test)
Since a pointer to temp is passed to the function, we, as programmers can guess that this function is supposed to initialize temp. But that is very difficult, if not impossible, for the compiler to assert with absolute certainity, specially when that function is in separate translation unit. From compilers perspective, there is no easy way to tell whether logcat will write to *temp or read it first in uninitialized state. And that's why the warning.
The easiest way to get rid of this warning is assign some initial value to temp, like:
int temp = 0
int fn();
void whatever()
{
(void) fn();
}
Is there any reason for casting an unused return value to void, or am I right in thinking it's a complete waste of time?
David's answer pretty much covers the motivation for this, to explicitly show other "developers" that you know this function returns but you're explicitly ignoring it.
This is a way to ensure that where necessary error codes are always handled.
I think for C++ this is probably the only place that I prefer to use C-style casts too, since using the full static cast notation just feels like overkill here. Finally, if you're reviewing a coding standard or writing one, then it's also a good idea to explicitly state that calls to overloaded operators (not using function call notation) should be exempt from this too:
class A {};
A operator+(A const &, A const &);
int main () {
A a;
a + a; // Not a problem
(void)operator+(a,a); // Using function call notation - so add the cast.
At work we use that to acknowledge that the function has a return value but the developer has asserted that it is safe to ignore it. Since you tagged the question as C++ you should be using static_cast:
static_cast<void>(fn());
As far as the compiler goes casting the return value to void has little meaning.
The true reason for doing this dates back to a tool used on C code, called lint.
It analyzes code looking for possible problems and issuing warnings and suggestions. If a function returned a value which was then not checked, lint would warn in case this was accidental. To silence lint on this warning, you cast the call to (void).
Casting to void is used to suppress compiler warnings for unused variables and unsaved return values or expressions.
The Standard(2003) says in §5.2.9/4 says,
Any expression can be explicitly converted to type “cv void.” The expression value is discarded.
So you can write :
//suppressing unused variable warnings
static_cast<void>(unusedVar);
static_cast<const void>(unusedVar);
static_cast<volatile void>(unusedVar);
//suppressing return value warnings
static_cast<void>(fn());
static_cast<const void>(fn());
static_cast<volatile void>(fn());
//suppressing unsaved expressions
static_cast<void>(a + b * 10);
static_cast<const void>( x &&y || z);
static_cast<volatile void>( m | n + fn());
All forms are valid. I usually make it shorter as:
//suppressing expressions
(void)(unusedVar);
(void)(fn());
(void)(x &&y || z);
Its also okay.
Since c++17 we have the [[maybe_unused]] attribute which can be used instead of the void cast.
Cast to void is costless. It is only information for compiler how to treat it.
For the functionality of you program casting to void is meaningless. I would also argue that you should not use it to signal something to the person that is reading the code, as suggested in the answer by David. If you want to communicate something about your intentions, it is better to use a comment. Adding a cast like this will only look strange and raise questions about the possible reason. Just my opinion...
As of C++11 you can also do:
std::ignore = fn();
This should achieve the same result on functions marked with [[nodiscard]]
C++17 [[nodiscard]]
C++17 standardized the "return value ignored business" with an attribute.
Therefore, I hope that compliant implementations will always warn only when nodiscard is given, and never warn otherwise.
Example:
main.cpp
[[nodiscard]] int f() {
return 1;
}
int main() {
f();
}
compile:
g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -o main.out main.cpp
outcome:
main.cpp: In function ‘int main()’:
main.cpp:6:6: warning: ignoring return value of ‘int f()’, declared with attribute nodiscard [-Wunused-result]
6 | f();
| ~^~
main.cpp:1:19: note: declared here
1 | [[nodiscard]] int f() {
|
The following all avoid the warning:
(void)f();
[[maybe_unused]] int i = f();
I wasn't able to use maybe_unused directly on the f() call:
[[maybe_unused]] f();
gives:
main.cpp: In function ‘int main()’:
main.cpp:6:5: warning: attributes at the beginning of statement are ignored [-Wattributes]
6 | [[maybe_unused]] f();
| ^~~~~~~~~~~~~~~~
The (void) cast working does not appear to be mandatory but is "encouraged" in the standard: How can I intentionally discard a [[nodiscard]] return value?
Also as seen from the warning message, one "solution" to the warning is to add -Wno-unused-result:
g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result -o main.out main.cpp
although I wouldn't of course recommend ignoring warnings globally like this.
C++20 also allows you to add a reason to the nodiscard as in [[nodiscard("reason")]] as mentioned at: https://en.cppreference.com/w/cpp/language/attributes/nodiscard
GCC warn_unused_result attribute
Before the standardization of [[nodiscard]], and for C before they finally decide to standardize attributes, GCC implemented the exact same functionality with the warn_unused_result:
int f() __attribute__ ((warn_unused_result));
int f() {
return 1;
}
int main() {
f();
}
which gives:
main.cpp: In function ‘int main()’:
main.cpp:8:6: warning: ignoring return value of ‘int f()’, declared with attribute warn_unused_result [-Wunused-result]
8 | f();
| ~^~
It should be noted then that since ANSI C does not have a standard for this, ANSI C does not specify which C standard library functions have the attribute or not and therefore implementations have made their own decisions on what should or not be marked with warn_unuesd_result, which is why in general you would have to use the (void) cast to ignore returns of any calls to standard library functions to fully avoid warnings in any implementation.
Tested in GCC 9.2.1, Ubuntu 19.10.
Also when verifying your code complies to MISRA (or other) standards, static-analysis tools such as LDRA will not allow you to call a function that has a return type without having it return a value unless you explicitly cast the returned value to (void)
Hopefully this is a very simple question. Following is the C pgm (test.c) I have.
#include <stdio.h>
//#include <stdlib.h>
int main (int argc, char *argv[]) {
int intValue = atoi("1");
double doubleValue = atof("2");
fprintf(stdout,"The intValue is %d and the doubleValue is %g\n", intValue, doubleValue);
return 0;
}
Note that I am using atoi() and atof() from stdlib.h, but I do not include that header file. I compile the pgm (gcc test.c) and get no compiler error!
I run the pgm (./a.out) and here is the output, which is wrong.
The intValue is 1 and the doubleValue is 0
Now I include stdlib.h (by removing the comments before the #include) and recompile it and run it again. This time I get the right output:
The intValue is 1 and the doubleValue is 2
How come the compiler did not complain about not including the stdlib.h and still let me use the atoi(), atof() functions?
My gcc info:
$ gcc --version
gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)
Any thoughts appreciated!
For historical reasons -- specifically, compatibility with very old C programs (pre-C89) -- using a function without having declared it first only provokes a warning from GCC, not an error. But the return type of such a function is assumed to be int, not double, which is why the program executes incorrectly.
If you use -Wall on the command line, you get a diagnostic:
$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:5: warning: implicit declaration of function ‘atoi’
test.c:6: warning: implicit declaration of function ‘atof’
You should use -Wall basically always. Other very useful warning options for new code are -Wextra, -Wstrict-prototypes, -Wmissing-prototypes, -pedantic, and -Wwrite-strings, but compared to -Wall they have much higher false positive rates.
Tangentially: never use atoi nor atof, they hide input errors. Use strtol and strtod instead.
If you don't specify otherwise, I believe a C compiler will just guess that undeclared functions take the form extern int foo(). Which is why atoi works and atof doesn't. Which compiler flags were you using? I suggest using -Wall to turn on a bunch of gcc warnings, which should include referencing undeclared functions.
C allows you to call a function without having a declaration for that function.
The function will be assumed to return an int and arguments will be passed using default promotions. If those don't match what the function actually expects, you'll get undefined behavior.
Compilers will often warn for this case, but not always (and that will also depend on compiler configuration).
In C, when you use a function that was not declared, it assumes that it has the default prototype:
int FUNCTION_NAME();
Note that in C using () as prototype means it accepts any arguments.
If you compile with the flag -Wall (I recommend you to always use this flag, since it enables all recommended warnings) you will get a warning (not an error) telling you that you are using an undeclared function.
C, unfortunately, does not require functions to be prototyped (or even declared) before use -- but without a prototype, it automatically makes certain assumptions about the function. One of those is that it returns an int. In your case, atoi does return an int, so it works correctly. atof doesn't, so it doesn't work correctly. Lacking a prototype/declaration, you get undefined behavior -- typically it'll end up retrieving whatever value happens to be in the register where an int would normally be returned, and using that. It appears that in your particular case, that happens to be a zero, but it could just as easily be something else.
This is one of the reasons many people push "C++ as a better C" -- C++ does require that all functions be declared before use, and further that you specify the types of all (non-variadic) parameters as well (i.e. a C++ function declaration is like a C prototype, not like a C declaration).