Reputation: 291
(1)
#include <stdio.h>
#include <stdlib.h>
int a = 10, b = 20 , c = 30, d, e, *pa, *pb, *pc;
d= 10;
e= 100;
pa = &a;
pb = &b;
int main()
{
printf("%i, %i, %i, %i", pa, pb, d, e);
return 0;
}
(2)
#include <stdio.h>
#include <stdlib.h>
int a = 10, b = 20 , c = 30, d, e, *pa, *pb, *pc;
d= 10;
e= 100;
int main()
{
pa = &a;
pb = &b;
printf("%i, %i, %i, %i", pa, pb, d, e);
return 0;
}
Why do I get an error when I initialize the pointer variables pa and pb outside of the main function (1)? When pa and pb are inside the main function it works perfectly fine (2). Why can I initialize normal variables outside of the main function (d,e) but not pointer variables?
The error message I get in CodeBlocks is: Conflicting file types for pa. Previous declaration of pa was here: line 4.
Upvotes: 3
Views: 5174
Reputation:
You can initialize pointers outside main()
, but declaration needs definition subsequently. Check the code:
#include <stdio.h>
#include <stdlib.h>
int a = 10, b = 20 , c = 30, d, e;
d= 10;
e= 100;
int *pa = &a;
int *pb = &b;
int main()
{
printf("%p, %p, %i, %i", pa, pb, d, e);
return 0;
}
Upvotes: 4
Reputation: 123468
Assignment and initialization are different operations.
int *pa = &a;
is a declaration with an initializer, and can occur within a function or at file scope.
int *pa;
pa = &a;
is a declaration followed by an assignment statement. Assignment statements (like any other executable statement) must occur within the body of a function.
I'm going to guess that this is an older compiler that still allows implicit int
declarations, so it's treating the statements
d = 10;
e = 100;
as defining declarations with initializers, not as assignment statements. It sees the previous declaration of d
and e
as non-defining declarations, and since they were declared int
, there's no conflict.
By contrast, the statements
pa = &a;
pb = &b;
are being treated as implicit int
declarations with initializers, but since you previously declared them as int *
, the compiler complains about a type mismatch.
Note: there is a problem with your output statement.
printf("%i, %i, %i, %i", pa, pb, d, e);
If you want to print the integer values in the variables that pa
and pb
point to, then you must dereference them in the printf
call:
printf("%i, %i, %i, %i", *pa, *pb, d, e);
If you want to print the pointer values stored in pa
and pb
, then you must use the %p
conversion specifier:
printf("%p, %p, %i, %i", (void *)pa, (void *)pb, d, e);
as well as cast the pointer value to void *
(this pretty much the only time you explicitly cast a pointer to void *
in C).
Upvotes: 0
Reputation: 141574
Executable code must go inside functions. This is because the flow of execution of a C program begins with calling main()
.
Lines like int a = 10;
are called declarations and they may be considered to "happen" before the program starts. Typically the compiler will generate a bloc of all of the global variables' data and load that up when it is starting up your program.
When you write d = 10;
at file scope, this is treated as int d = 10;
. Since statements are not permitted at file scope, it is not an assignment statement. The compiler thinks it is a declaration where you meant to write int
but wanted to save typing by leaving it out.
This is called implicit int and C89 had it, although it was removed in C99.
So when you write pa = &a;
, implicit int makes it int pa = &a;
and you get an error because you have declared pa
with type int *
and then again with int
, which are different types.
However declaring a variable as int
and then re-declaring it as int
(as you did for d
and e
) is fine so long as the first one didn't have an initializer. This is called tentative definition.
To avoid all this, make sure that any code that isn't meant to be a declaration goes inside a function. You could write at file scope:
int a = 5;
int *pa = &a;
and so on.
Also, printf("%i, %i, %i, %i", pa, pb, d, e);
causes undefined behaviour. The %i
specifier must match to an int
. To fix this you either need to pass (int)pa
instead of pa
, etc., or use the %p
specifier.
Upvotes: 6