4

I ran the following codes using ideone.com:

#include <stdio.h>

int main(void)
{
    int i,j=0;
    if(j)
    {
        j=0; //To suppress the warning that j is not used
        i=1;
    }
    printf("%d\n",i);
}

Output: Garbage value:

 #include <stdio.h>

 int main(void)
 {
      int i;
      if(0)
      {         
        i=1;
      }
      printf("%d\n",i);
 }

Output:

Error: unitialized local variable i used.

Is it because the compiler removes the if(0) block completely while optimizing? And such an optimization cannot be done in case of if(j) since it is a variable? Won't value of j be present at compile-time and the same optimization must be done? Or is it that memory is allocated at run-time only?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
user2684198
  • 812
  • 1
  • 10
  • 18
  • 1
    imo, it's a failure of gcc (and clang) to detect that i might be used without being initialized in the 1. case. Compilers arn't required to detect that though, but ideone.com compiles with the `-Werror` flag, so when it does detect this, the compilation fails, instead of issuing a warning. – nos Jun 23 '14 at 13:58
  • Is it because the compiler removes the if(0) block completely while optimizing? yeah probably. thats pretty hard to identify otherwise. lint would never have gotten something like this – Steve Cox Jun 23 '14 at 14:00
  • Could you compile with -O3 to see if it will figure out the error in the first case? – Steve Cox Jun 23 '14 at 14:04
  • Does anyone actually use `if(0) { ... }` in real code? I always see it written as `#if 0` ... `#endif` if your intention is to comment out a block – Brandin Jun 23 '14 at 22:32
  • Please mention the compiler name and version that you are using (ideone supports a range of compilers) – M.M Jun 23 '14 at 22:33
  • By the way, the second example generates an error but in most implementations it would only generate a warning. Printing an uninitialized variable results in undefined behavior, so it's good that your implementation prints a diagnostic, but still you should be able to compile it if you want. UB doesn't start until you actually execute that line. – Brandin Jun 23 '14 at 22:36

2 Answers2

3

As far as I can tell Ideone is using gcc, the code you are using must be using -Werror since normally -Wuninitialized would just be a warning but if used in conjunction with -Werror will turn it into an error. We can see that when this warning is triggered is very dependent on your optimization settings and version of gcc, their documents say:

Because these warnings depend on optimization, the exact variables or elements for which there are warnings depends on the precise optimization options and version of GCC used.

Note that there may be no warning about a variable that is used only to compute a value that itself is never used, because such computations may be deleted by data flow analysis before the warnings are printed.

Of all the online compilers available I prefer Coliru when I want to experiment with compiler flags and different compilers since it allows the most straight forward way to manipulate them.

At the end of the day using an uninitialized variable is undefined behavior and the compiler is not obliged to generate a warning for this, the compiler can do very unexpected things with undefined behavior as the quesiton Why does this code output more than 4 lines? demonstrates.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Specifically, many warnings are determined after optimization, not before. The unused variable warning is only evaluated after unused basic blocks are removed. Whether a basic block is unused depends heavily on how aggressive the optimization is. – Steve Cox Jun 23 '14 at 14:15
  • Where is he asking specially for gcc? didn't catch that sentense – dhein Jun 23 '14 at 14:23
  • @Zaibis he is used ideone which as far as I can tell is using `gcc`. This is based on their error message which differs from `clang` and as far as I know Rextester is the only online compiler that uses Visual Studio. – Shafik Yaghmour Jun 23 '14 at 14:26
  • @ShafikYaghmour: Is not the code user presented UB? –  Jun 23 '14 at 14:34
  • @dmcr_code you read my mind, I was just editing that in, although it is somewhat incidental to the core of the question it is good to note. – Shafik Yaghmour Jun 23 '14 at 14:36
  • @ShafikYaghmour: I think it is good to note; I think it is UB due to reading uninitialized variable –  Jun 23 '14 at 14:39
  • Its undefined behavior at runtime, but not at compile time. I imagine OP is asking the question because he wants to avoid the undefined behavior, and likes it when the compiler identifies it for him, without having to go to valgrind to check where it happens. – Steve Cox Jun 23 '14 at 14:41
2

From ISO/IEC:9899 TC3

5.1.1.3 Diagnostics 1 A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances.8)

So the point is, the compiler can feel free about throwing a warning or doing not so, as in case of undefined behavior, he can feel free of doing so or not in that case.

So, maybe there is some special optimisation reason. but maybe they just have a routine which is such case just checking partial, as the don't have to catch thoose cases at all.

dhein
  • 6,431
  • 4
  • 42
  • 74
  • 1
    This really isn't a question about the standard. OP is clearly asking about how specific implementations handle this situation, and why. – Steve Cox Jun 23 '14 at 14:40
  • hm don't get that, but if the OPer may comment me that too, I will take my answer out ofc. – dhein Jun 23 '14 at 14:41
  • 1
    `Is it because the compiler removes the if(0) block completely while optimizing? And such an optimization cannot be done in case of if(j) since it is a variable?` The moment you mention optimization, you are talking about an implementation, not the standard. This answer is fine though, its the overarching answer for why compilers can do whatever they want, it just doesn't answer anything specific. – Steve Cox Jun 23 '14 at 14:44