11

I finally trace down a typo bug, which is something similar to the following code. But shouldn't the compiler detect this (by default options)?

#include <stdio.h>

int main()
{
    int c = c;
    return printf("%d\n", c);
}


$ gcc --version        
gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
user207421
  • 305,947
  • 44
  • 307
  • 483
user180574
  • 5,681
  • 13
  • 53
  • 94
  • 10
    You invoke undefined behaviour with the initialization; the compiler is not require to diagnose the problem, or to define what it does when it encounters it. – Jonathan Leffler Apr 19 '13 at 17:47
  • 8
    I'd bet my left shoe that when you turn on warnings (-Wall in GCC), it will warn you when you're doing this. Try not to ignore warnings ;-) – nothrow Apr 19 '13 at 17:48
  • 3
    I used GCC 4.7.1 with compiler options: `gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -c x.c` and the complaints were about 'not a prototype' and 'old-style function definition' and not about the variable initialization. OTOH, `clang` diagnosed: `x.c:5:13: warning: variable 'c' is uninitialized when used within its own initialization [-Wuninitialized]` (but adding `-Wuninitialized` to the GCC options didn't add to the messages — `clang` has better diagnostics here). – Jonathan Leffler Apr 19 '13 at 18:00
  • @JonathanLeffler, good point. I assumed that this is really something GCC should point out, but I assume it thinks that `c` is initialized (with `c` :-) ) – nothrow Apr 19 '13 at 18:17
  • 5
    gcc has a `-Winit-self` flag. – effeffe Apr 19 '13 at 18:23
  • 1
    @nothrow give me your shoe, `-Wall -Wextra` does not include `-Winit-self` in GCC 4.9.3. – Ciro Santilli OurBigBook.com May 08 '17 at 16:56
  • Also see [C++ version of this question](https://stackoverflow.com/q/23415661/1708801) – Shafik Yaghmour Sep 18 '18 at 18:33

2 Answers2

7

I don't see why it wouldn't compile. Definition happens prior to initialization. Of course this initialization is pointless, however, there's no reason it wouldn't work from the compilers stand point.

C does not have the same types of protections that more modern languages like C# have. The C# compiler would give an error that you're using an unassigned variable. C doesn't care. It will not protect you from yourself.

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
  • 5
    This initialization, not assignment. – Eric Postpischil Apr 19 '13 at 18:14
  • 5
    Also, being able to refer to the variable for its initialization is *useful*, because you can take its address, as in `int x = initialize_and_register(&x)`. (That kind of invocation would typically be packaged in a macro.) – user4815162342 Apr 20 '13 at 00:59
  • @user4815162342 true, that obviously makes sense. I should have chosen my words better :( – evanmcdonnal Apr 20 '13 at 03:24
  • Your words are quite fine (except for the distinction between initialization and assignment), I was just offering a suggestion for a further improvement of the answer. Your answer doesn't make it clear that there are cases where using `x` in an expression initializing `x` is actually useful, so it's not (only) about C not protecting you from yourself. And if you wish to add that info to the answer, that's what the "Edit" button is for. :) – user4815162342 Apr 20 '13 at 07:16
  • 1
    That's why C "warnings" exist : they don't trigger an error, but merely warn the programmer about a suspicious pattern. – Cyan Jul 02 '15 at 23:31
4

It's perfectly legitimate to use a variable in its own initializer. Consider a linked list:

#include <stdio.h>
struct node { struct node *prev, *next; int value; };
int main() {
    struct node l[] = {{0, l + 1, 42}, {l, l + 2, 5}, {l, 0, 99}};
    for (struct node *n = l; n; n = n->next)
        printf("%d\n", n->value);
    return 0;
}

In general, diagnosing when a value is used uninitialised is a difficult problem; although some compilers can detect it in some cases it doesn't make sense to require it to happen.

ecatmur
  • 152,476
  • 27
  • 293
  • 366