3

(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.

4
  • (I am not sure) But I believe that you cannot put statements outside your main to execute like you would expect them to in your main. Though you can declare variables. I believe that when you write pa = &a by that time you compiler doesn't know that you have already declared pa. Further, if you do not give a data type, it is automatically taken as int so, when you write pa the compiler makes it int pa (without taking into consideration of your previous declaration) and then you try to assign a pointer to your int that why it gives you an error! Commented Jul 23, 2015 at 1:16
  • The memory allocation happens only after main Commented Jul 23, 2015 at 1:17
  • @purpletech that's not allocation, globals do not reside in heap space Commented Jul 23, 2015 at 1:20
  • 1
    The d= 10;, pa = &a;, etc. lines are redeclaring those variables, not just setting their value... this is allowed at file scope provided the types match the earlier declarations. Since you don't give the type on those lines, it's assumed to be int, so it matches the earlier declaration for d and e, but not for pa and pb. Commented Jul 23, 2015 at 1:41

3 Answers 3

6

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.

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

3 Comments

More like: "Executable code must go inside functions. This is because ... that's the way it is in C," C++ programs also have main, yet there can be executable code outside functions (global initializers and constructors). C compilers have extensions for running code before main, like GCC's constructor attributes (together with appropriate run-time support).
@Kaz this is a C question
@Kaz my answer , being posted to a C question, should be understood as only applying to C. I have updated that sentence to clarify.
4

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;
 }

2 Comments

But that way you removed the declaration from the first line. Is it possible to declare it in one line and initialize it in an other line (outside of main) just like regular variables?
in your code we just saw that separate declaration and separate definition in different lines doesn't work outside main - I still don't have a reason for this.
0

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.