differnces between declaration and definition of functions and global variables.

hi,
i have confusion regarding access of global variables and functions. i know that global variable can only be accessed with extern syntax but function can be accessed from anywhere declaring its prototype. why global variable can't have a prototype? what is the process behind compiler which restricts from declaring global variables like we do with functions.

//code file1.cpp
#include<iostream>
printHello();
int testInteger;
int main(){
printHello();
std::cout<<testInteger<<std::endl;

}

//code file2.cpp

#include<iostream>
int testInteger=34;
printHello(){
std::cout<<testInteger<<std::endl;
}


in above two translation unit. i know we must use extern to use testInteger in file1 from file2. BUT why declaration of testInteger in file1 and definition in file2 restricted? why we can't do like above code? we can declare functions multiple times and define it once in any translation unit.
what is difference? i know we will get multiple definition error but why it happens? is declaration of integer itself is the definition of that integer?
please illustrate this explaining the process the compiler and linker works with function of this declaration and definition of functions and global variables.
I know that global variable can only be accessed with extern syntax but function can be accessed from anywhere declaring its prototype. why global variable can't have a prototype?

That "extern syntax" is exactly the equivalent of a function prototype. extern int testInteger; declares a variable without defining it.

we can declare functions multiple times and define it once in any translation unit. what is difference?

No difference. You can declare a global variable multiple times an define it only once in one translation unit.

is declaration of integer itself is the definition of that integer?

Every definition is also a declaration, not every declaration is a definition. int testInteger; is a definition (and a declaration). extern int testInteger; is a declaration, but not a definition.
All header files do is tell the compiler that some thing (variable, constant, function, etc) exists somewhere else, just not in this file.

So, suppose you have a file:

1
2
3
4
5
6
7
8
// next.cpp

int the_next_value = 0;

int get_next_value()
{
  return the_next_value++;
}

The compiler can build that into code, but in order to use it, other files need to know that the things in it exist. You do that with prototypes and extern declarations.

  • A prototype declares that some function exists somewhere
  • An extern declares that some value (not a function) exists somewhere

1
2
3
4
5
6
7
8
9
10
11
12
13
// main.cpp

#include <iostream>

extern int the_next_value;        // This exists somewhere (just not here)
int get_next_value();             // This also exists somewhere (just not here)

int main()
{
  the_next_value = 7;
  std::cout << get_next_value() << "\n";
  std::cout << get_next_value() << "\n";
}

Now when the compiler compiles main.cpp, it also knows what the things in next.cpp look like. Once both main.cpp and next.cpp are compiled, they can be linked together to produce an executable.

C:\Users\Katie\prog> g++ main.cpp next.cpp -o myprog
C:\Users\Katie\prog> myprog
7
8
C:\Users\Katie\prog>

Now we run into a potential other problem: every time we want a new cpp file that uses the stuff in next.cpp we have to repeat all the extern and prototype declarations. Over and over and over. What a headache!

Instead, we write a header file that does that for us:

1
2
3
4
5
6
7
8
// next.hpp
#ifndef NEXT_HPP
#define NEXT_HPP

extern int the_next_value;
int get_next_value();

#endif 

Now all we need to do is directly include the contents of that header file in any cpp file we wish.

1
2
3
4
5
6
7
8
9
10
11
12
// main.cpp

#include <iostream>

#include "next.hpp"

int main()
{
  the_next_value = 7;
  std::cout << get_next_value() << "\n";
  std::cout << get_next_value() << "\n";
}

This is exactly how the standard include files work. For example, when you #include <iostream> , you are getting reference to three objects:

  • std::cin
  • std::cout
  • std::cerr

Just like the_next_value, these three objects are declared extern by the iostream header. The compiler automatically links the cpp file that actually has the standard I/O objects in it to your executable. Using the #include directive lets you use them in any cpp file you wish.

For those of you who know better, this is a very simplified explanation. Don't get hung up on details!

Finally, to answer your actual question:

  • A declaration only tells the compiler that something exists and what it looks like
  • A definition not only declares something, but it gives all the implementation details too.

Hope this helps.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// declaration of a function: that this is only a declaration is implied;
// the definition of a function would have a function-body { /* ... */ }
// since the body is not present, this must be just a function declaration
// by default, functions have external linkage; so extern is implied
int foo( int a ) ;

// same as above (the extern specifier is permitted, but not required)
extern int foo( int a ) ;

int foo( int a )
{ return a*2 ;  } // this is the function body: ergo this is the function definition



// for objects, by default, every declaration is also deemed to be a definition
int x ; // definition of x (with default initialisation)

// however, with the extern specifier, and without an initialiser it is only a declaration
extern int y ; // declares y (this is not a definition)

// int x // *** error: redefinition of x
extern int x ; // fine: this is only a declaration (redeclaration is permitted)

extern int y = 23 ; // defines y (has an initialiser, ergo definition)
// the extern specifier here is permitted, but not required



// in general, where a definition requires that a body be present,
// the absence of a body implies that it is only a declaration
struct A ; // declares A

struct A { /* class definition */ }; // defines A

struct A ; // declares A (redeclaration is permitted) 
Topic archived. No new replies allowed.