12

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
7
  • 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. Commented Apr 19, 2013 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 ;-) Commented Apr 19, 2013 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). Commented Apr 19, 2013 at 18:00
  • 5
    gcc has a -Winit-self flag. Commented Apr 19, 2013 at 18:23
  • 1
    @nothrow give me your shoe, -Wall -Wextra does not include -Winit-self in GCC 4.9.3. Commented May 8, 2017 at 16:56

2 Answers 2

8

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.

Sign up to request clarification or add additional context in comments.

5 Comments

This initialization, not assignment.
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 true, that obviously makes sense. I should have chosen my words better :(
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. :)
That's why C "warnings" exist : they don't trigger an error, but merely warn the programmer about a suspicious pattern.
5

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.

3 Comments

How is undefined behavior legitimate?
This isn't quite initializing a variable with itself, but rather a pointer to itself, since l decays into a pointer &[0] in this context.
@this in this particular case (array-to-pointer decay), yes. In most cases it would not be.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.