user1508519
user1508519

Reputation:

Redefinition of a pointer in global scope

In this question I am thoroughly confused about this seemingly basic aspect of C. Consider these two lines of code:

int *ptr;
*ptr = 2;

gcc will emit the following warnings:

main.cpp:4:1: warning: data definition has no type or storage class [enabled by default]

 *ptr = 2;
 ^
main.cpp:4:2: warning: type defaults to 'int' in declaration of 'ptr' [enabled by default]

 *ptr = 2;
  ^
main.cpp:4:8: warning: initialization makes pointer from integer without a cast [enabled by default]

 *ptr = 2;
        ^

What type is ptr being defaulted to, int or int* (as in, is ptr a pointer, or an int)? If so, does this mean that ptr is pointing to address 2, or is that unchanged? I would assume that it's changed because it crashes unless you give ptr a valid address.

int i = 5;
int *ptr;
*ptr = &i;

int main(){
    printf("%d", *ptr); // 5
}

I am aware of the possibility of undefined behavior and that you shouldn't ignore warnings, but I'm trying to see what actually happens here.

For context, see the comment chain under this answer.

Upvotes: 9

Views: 1913

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726699

Here is what's going on: since the two lines that you are showing are in the file scope (as opposed to a local scope) both lines are treated as declarations, not as a declaration and an assignment statement. This is because there could be no statements at the file scope - only declarations and definitions are allowed.

Old C rules allowed declarations of type int to omit type altogether. Therefore, the second line is

  • A declaration / definition of ptr
  • ...which is a pointer, because it has an asterisk
  • ...and it is also a pointer to int, because the type is missing.

That last rule is very archaic, and it has been deprecated in the ANSI version of the language standard. That is why you get a warning. If you change your code to

int *ptr;
int *ptr = &i;

your code is going to compile and run (demo).

Now one question remains: how come the compiler does not complain about duplicate declarations? It turns out that the compiler will treat multiple identical declarations as one and the same, as long as they are entirely identical to each other.

Upvotes: 13

Related Questions