Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » extern?

This thread is locked; no one can reply to it. rss feed Print
 1   2 
extern?
Albin Engström
Member #8,110
December 2006
avatar

Seems like i misunderstood a part of Tobias generously written tutorial:

Tobias Dammers said:

6. For each variable that you want to be accessible from the outside, put an "extern" reference in the module's header:

// ---- module.h ----
#ifndef MODULE_H
#define MODULE_H

extern int this_is_globally_available;

#endif
// ---- module.cpp ----
int this_is_globally_available = 23;

I just want to know what extern does, because it doesn't do what i thought it would do, which is enabling the use of the variable outside the corresponding .cpp file.

oh, and about that, does a .cpp file has to have same name as the header file? (didn't know how to put it into words)

X-G
Member #856
December 2000
avatar

It says "this variable may exist in a different compilation unit". In other words, exactly what you think it does. As for your second question, no, of course not. Why would it?

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Albin Engström
Member #8,110
December 2006
avatar

X-G said:

It says "this variable may exist in a different compilation unit". In other words, exactly what you think it does.

eer.. ok ^^'

X-G said:

As for your second question, no, of course not. Why would it?

i shouldn't be asking questions so early in the morning..

thanks X-G :P..

Kris Asick
Member #1,424
July 2001

Quote:

I just want to know what extern does, because it doesn't do what i thought it would do, which is enabling the use of the variable outside the corresponding .cpp file.

"extern" means that the variable you're referencing is not defined in the file you've declared it in and that the linker should find a match for it after compiling.

Remember, there are two basic steps to compiling a program: The actual compiling of each source file and then linking them. That's when extern variables are resolved and their non-extern counterparts linked.

Which follows into your second question:

Quote:

oh, and about that, does a .cpp file has to have same name as the header file? (didn't know how to put it into words)

A header file is just that, a header. When you compile a specific source file, all #included headers have their contents added to where you #included them. (Which is why the order you include headers is important sometimes.)

Because of this, headers and source files don't need to match. In fact, you don't even have to USE header files, you can do all your header file stuff at the front of your file. But without a header, other programs source files wouldn't be able to access your source.

Note that #include can include any kind of file, even source files.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

--- Kris Asick (Gemini)
--- http://www.pixelships.com

Albin Engström
Member #8,110
December 2006
avatar

Kris Asick said:

When you compile a specific source file, all #included headers have their contents added to where you #included them. (Which is why the order you include headers is important sometimes.)

Is it possible put #include anywhere??

Kris Asick said:

Because of this, headers and source files don't need to match. In fact, you don't even have to USE header files, you can do all your header file stuff at the front of your file. But without a header, other programs source files wouldn't be able to access your source.

but i don't include source files (since this far, i've been told not to, but your(mine?) third quote attacks this information and i'll have to request another question,,), so i thought it was something automatic.. how does the compiler know it should include the .cpp files?? and more importantly, why using both?? if it's only including code?

Kris Asick said:

Note that #include can include any kind of file, even source files.

I'm certain that i've been told this shouldn't be done. care to explain? :)

thank you very much!

X-G
Member #856
December 2000
avatar

Quote:

Is it possible put #include anywhere?

Practically anywhere. Maybe not, like, in the middle of a line.

Quote:

words

You don't include .cpp files. You include .h files (and .hpp files). That's it.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

HoHo
Member #4,534
April 2004
avatar

Compiler doesn't know what is in other .cpp files. When you include .h files it will see the declarations there. When linking together the .o files created by compiler all the .cpp files come together into single executable.

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

TeamTerradactyl
Member #7,733
September 2006
avatar

The pre-processor sees an #include, and immediately grabs whatever file you specify and sticks it there. Say you had comments.txt and you wanted to add them to your code.cpp:

comments.txt:

   // This file only contains comments about the current function.  It is here to... blah blah blah...
   // There is no actual code here, just comments.

code.cpp:

   int main(void)
   {
      ...
      // I want to add comments here from my other file so others who read my sources
      // can understand where I'm coming from...
#include comments.txt
      ...
   }

When the pre-processor sees this, it will actually take all those lines and merge them together:

   int main(void)
   {
      ...
      // I want to add comments here from my other file so others who read my sources
      // can understand where I'm coming from...
   // This file only contains comments about the current function.  It is here to... blah blah blah...
   // There is no actual code here, just comments.
      ...
   }

The PROBLEMS with the above example, however, is that although you stuck your comments into this code, they're just comments, and the compiler ignores them completely. So the above example is useless (but I thought I'd have fun writing useless code just because I can, for illustration).

But yes, you can #include files anywhere within your code.

One place I can actually see this really useful halfway down into the source code, is if you are compiling for different OS's (like Linux or Windows) that calls machine-specific functions.

Anyway, that's just my 2 cents...

Albin Engström
Member #8,110
December 2006
avatar

seriously... backspace sucks. (this is a little of-topic but: i use firefox and i really need to remove the backspace shortcut, thanks in advance..)

back to the topic..

what's the difference between a .h and .hpp file?

i thank thee for your answers, but i'm afraid i have some more questions :):

i have the following project:

main.cpp | initialization.cpp | initialization.h

initialization.h looks like this:

#ifndef INITIALIZATION_H
#define INITIALIZATION_H

void static_initialization();
void dynamic_initialization();
void de_initialization();

bool fullscreen;

#endif

now, as i try to compile my experimental project on how to link files and stuff i get the following error " multiple definition of `fullscreen'"

initialization.h is included in both main.cpp and initialization.cpp
i thought #ifndef INITIALIZATION_H would handle this kind of problem?

moving on: i changed "bool fullscreen" to "extern bool fullscreen" and added a global variable to main.cpp making it look like this:

1#include <allegro.h>
2#include "initialization.h"
3 
4bool fullscreen;
5 
6int main()
7{
8 static_initialization();
9 dynamic_initialization();
10
11 while(!key[KEY_ESC])
12 {//main loop
13
14
15 if(fullscreen==true)break;
16 }//main loop
17
18}END_OF_MAIN()

and the "initialization.cpp" into this:

1#include <allegro.h>
2#include "initialization.h"
3 
4void static_initialization()
5{
6 allegro_init();
7
8 install_timer();
9 install_keyboard();
10 install_mouse();
11
12 set_config_file("config.ini");
13};
14 
15void dynamic_initialization()
16{
17 fullscreen = true;
18
19 set_color_depth(16);
20
21 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
22
23};
24 
25void de_initialization()
26{
27};

from some experiments i determined that the global variable can't be accessed from
"initialization.cpp" without "extern bool fullscreen" in the "initialization.h" file.

this wasn't really what i wanted, as i don't know what to to if namespace is involved, (side question: is it a global variable if it's in a namespace?) and i'm not really fond of passing everything along with functions and sometimes it just feels unnecessary.. how do i use extern bla bla on something inside a namespace?

I hoped that i could have a header with the variables only usable by the sections #including the header :/. i hope you can tell me whenever it possible or not.

thank you very very much!

X-G
Member #856
December 2000
avatar

Quote:

what's the difference between a .h and .hpp file?

One is traditionally used for C, the other traditionally used for C++. There is no functional difference.

Quote:

from some experiments i determined that the global variable can't be accessed from "initialization.cpp" without "extern bool fullscreen" in the "initialization.h" file.

Why does this confuse you? That's exactly the intended behavior. I don't see where the confusion is coming from.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

ImLeftFooted
Member #3,935
October 2003
avatar

Maybe this will help: Every .cpp file lives in its own little world.

John.cpp doesn't know Kate.cpp, which sucks for john, cause hes single.

Luckily for John.cpp, there exists in the computer world a dating service! Now John.cpp can meet up with Kate.cpp!

Now everyone knows girls speak their own language, so John.cpp must figure this out. Luckily for him, Kate.cpp comes with an owners manual!

John.cpp looks up Kate.h (Kate's owners manual) and finds a number of extern interfaces! He sees extern void *boyfriend and decides to make the swoop.

Unfortunately for John.cpp, HotGuy.cpp also looks up Kate.h and makes the swoop for boyfriend.

The problem, ofcourse, is that Kate.cpp can only have 1 boyfriend. So there must be only one 'boyfriend' variable. HotGuy and John must be changing the same variable, because everyone knows a girl can only handle one boyfriend.

So you see, extern merely says "maybe Kate is looking for a boyfriend". The match maker will connect John and HotGuy later, if Kate allows it.

Now replace match maker with linker. *
* Really an approximation. Some facts were left out, twisted or plain fabricated. But who wants to hear boring mumbo jumbo anyway?

Quote:

I hoped that i could have a header with the variables only usable by the sections #including the header :/. i hope you can tell me whenever it possible or not.

A one-time #include header block will stop John from reading Kate's manual twice, but you have no control over what HotGuy decides to do.

Archon
Member #4,195
January 2004
avatar

You should know that header files are primarily for telling the file that is referencing what to expect... It's like an interface. That's why you go:

#include <allegro.h>

Because you don't know how Allegro works until you basically copy the header into your file using the #include statement.
The .cpp (source) file is just the implementation - the "how", but you personally don't need to know how Allegro works internally... You just need to know how to interface with it.

The extern variables are like interfaces to a variable - there'll only be one in the entire program that multiple files can reference, but that means that only one place can instantiate it...

Also, think of linking as just that... It brings the program (object files) together and it makes the variables, functions (etc) reference the respective code.

Albin Engström
Member #8,110
December 2006
avatar

X-G said:

One is traditionally used for C, the other traditionally used for C++. There is no functional difference.

:o how unnecessary...

X-G said:

Why does this confuse you? That's exactly the intended behavior. I don't see where the confusion is coming from.

It didn't confuse me, it was more of an introduction to the things i wrote after: "this wasn't really what i wanted, as i don't know what to to if namespace is involved, (side question: is it a global variable if it's in a namespace?) and i'm not really fond of passing everything along with functions and sometimes it just feels unnecessary.. how do i use extern bla bla on something inside a namespace?" (i figured this out) - -

Dustin Dettmer said:

Maybe this will help: Every .cpp file lives in its own little world.

John.cpp doesn't know Kate.cpp, which sucks for john, cause hes single.

Luckily for John.cpp, there exists in the computer world a dating service! Now John.cpp can meet up with Kate.cpp!

Now everyone knows girls speak their own language, so John.cpp must figure this out. Luckily for him, Kate.cpp comes with an owners manual!

John.cpp looks up Kate.h (Kate's owners manual) and finds a number of extern interfaces! He sees extern void *boyfriend and decides to make the swoop.

Unfortunately for John.cpp, HotGuy.cpp also looks up Kate.h and makes the swoop for boyfriend.

The problem, ofcourse, is that Kate.cpp can only have 1 boyfriend. So there must be only one 'boyfriend' variable. HotGuy and John must be changing the same variable, because everyone knows a girl can only handle one boyfriend.

So you see, extern merely says "maybe Kate is looking for a boyfriend". The match maker will connect John and HotGuy later, if Kate allows it.

Now replace match maker with linker. *

  • Really an approximation. Some facts were left out, twisted or plain fabricated. But who wants to hear boring mumbo jumbo anyway?

Fun to read, hard to understand :P. let me get this right: John.cpp has a variable, HotGuy.cpp also has that variable and Kate has the extern variable, but the extern variable can only be.. linked to one variable?(is that the right word?) :S. but what if John.cpp and HotGuy.cpp is interested in both boys and girls and they decide to have a 3p relationship, can HotGuy.cpp have his variable made extern and linked to John.cpp?

Archon said:

The extern variables are like interfaces to a variable - there'll only be one in the entire program that multiple files can reference, but that means that only one place can instantiate it...

sounds like pointers.. (although i haven't really read much about them so i don't know what i'm talking about..), anyway, i think i've got it right.

-.-?

Thanks for being kind enough to answer!!

Archon
Member #4,195
January 2004
avatar

Quote:

sounds like pointers..

Not really. That's like saying that the functions in header files are function pointers. They all act like any other ordinary variable once linked...

You do know that the program has to know where all of the variable and function addresses are in the memory. extern is just letting the variable get referenced by other files (but it's still not a pointer).

If you don't understand C++ so well, you could invest your interest in C# or Java (or even D). They share very similar syntax and should be easier to code with.

Albin Engström
Member #8,110
December 2006
avatar

Archon said:

If you don't understand C++ so well, you could invest your interest in C# or Java (or even D). They share very similar syntax and should be easier to code with.

Thats out of the question...

Joel Pettersson
Member #4,187
January 2004

Quote:

John.cpp has a variable, HotGuy.cpp also has that variable and Kate has the extern variable, but the extern variable can only be.. linked to one variable?(is that the right word?)

Nope. There is only one variable, which Kate.cpp has. The extern one - which John.cpp and HotGuy.cpp both find in Kate.h - refers to that variable, providing a means for accessing it.

bamccaig
Member #7,536
July 2006
avatar

I think extern deals with scope. Local scope is generally within a function or method.

int main(void)
{
    int intLocalScope = 0;  // Local scope. Nothing outside of main()
                            // knows about this.

    return intLocalScope;
}

Module scope, as I've heard it called, or class scope (might be more intuitive), is basically a class member or method that is private and only accessible to that class (or struct).

class Foo
{
private:
    int mintModuleScope;    // Module/Class scope. Nothing outside of Foo
                            // knows about this.
};

Global scope, is I think within a single file. For example, you can use it anywhere in that file. These are declared outside of classes, structs, and functions.

// myprogram.cpp
gintGlobalScope = 0;   // Global scope. Nothing outside of myprogram.cpp
                       // knows about this.

int main(void)
{
    return gintGlobalScope;
}

extern is basically a way to broaden the scope of a variable even further than the entire file. You can then share it between files. I was having trouble remembering how to do this a couple months ago. Hopefully I get it right:

// myprogram.h
int xintExternalScope = 0;    // This is simply declared normally. Current
                              // it has global scope to myprogram.h.

// myprogram.cpp

// xintExternalScope is defined in this file...
#include "myprogram.h"

extern xintExternalScope;    // This is saying that it is defined elsewhere
                             // (myprogram.h), but we're using it here as well.

int main(void)
{
    return xintExternalScope;
}

Albin Engström
Member #8,110
December 2006
avatar

Joel Pettersson said:

Nope. There is only one variable, which Kate.cpp has. The extern one - which John.cpp and HotGuy.cpp both find in Kate.h - refers to that variable, providing a means for accessing it.

ok, :P..

Great explanation bamccaig! thanks a lot! :)
removed a lot of uncertain thoughts.

one question: extern BITMAP??.. (fixed by putting #include <allegro.h> in a header? there isn't anything wrong with that right?)

bamccaig
Member #7,536
July 2006
avatar

I assume you should be able to use the extern keyword with any variable, including BITMAPs.

// file1.cpp
BITMAP *xobjBitmap;

// file2.cpp
extern BITMAP *xobjBitmap;

However, it's probably not necessary and, therefore, not a very good idea. You should only use global/external variables when it's absolutely necessary or cleans up the code. Always try to minimize the scope of a variable: only allow it as much scope as is necessary to function properly or clean up your code.

Why do you want to use extern with a BITMAP? Note that if you need access the BITMAP from functions in other files you can easily pass a reference instead of making it global/external:

// file1.cpp
#include <allegro.h>

void message_bitmap_dimensions(BITMAP *objBitmap)
{
    // Here we use the address to gain access to the BITMAP instance.
    allegro_message("The bitmap is %d wide and %d high!",
        objBitmap->w, objBitmap->h);
}

1// file2.cpp
2#include <allegro.h>
3 
4int main(void)
5{
6 /*
7 * Holds the address of a BITMAP instance. create_bitmap() instanciates an
8 * instance and returns the address of where the instance is stored.
9 */
10 BITMAP *objBitmap = create_bitmap(10, 10);
11 
12 // We pass the address of the BITMAP instance into a function.
13 message_bitmap_dimensions(objBitmap);
14 
15 // Clean up our BITMAP instance.
16 destroy_bitmap(objBitmap);
17 objBitmap = NULL;
18 
19 return 0;
20}

If you use an external variable than finding the source of it can require searching many source files. If you pass a reference/address instead it is easy to know where the data is coming from and makes the code more readable. Function parameters are used to share information between other functions. That's why it's generally frowned upon to use global or external variables. You should always try to minimize the scope of a variable to protect it from being modified where it shouldn't be.

ImLeftFooted
Member #3,935
October 2003
avatar

Quote:

let me get this right: John.cpp has a variable, HotGuy.cpp also has that variable and Kate has the extern variable ...

This is exactly right, only the opposite

Quote:

... but the extern variable can only be.. linked to one variable?

Multiple extern variables can be linked to a single 'real' variable.

Albin Engström
Member #8,110
December 2006
avatar

bamccaig said:

Why do you want to use extern with a BITMAP? Note that if you need access the BITMAP from functions in other files you can easily pass a reference instead of making it global/external:

yeah i know, but i don't like to pass.. - -. but i'll covert in time.

bamccaig said:

modified where it shouldn't be.

how is that possible?
variables don't change values by themself, right? - -

Dustin Dettmer said:

This is exactly right, only the opposite

^^'

bamccaig said:

Multiple extern variables can be linked to a single 'real' variable.

great :).

X-G
Member #856
December 2000
avatar

He means a module that shouldn't have access to the variable changing it. It's an encapsulation thing.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Albin Engström
Member #8,110
December 2006
avatar

ok..

Archon
Member #4,195
January 2004
avatar

Give us cookies, or give us death!

bamccaig
Member #7,536
July 2006
avatar

Albin Engström said:

variables don't change values by themself, right?

The rule is to reduce scope. Say you have a buffer BITMAP and declare it externally. Any file is then able to access your buffer, which means you could possibly collide with another buffer, for example, and things just get weird and you don't know why. That's just an example... It's possible to use global variables, as you are, but it's not a good practice. That's what parameters are for! {smiley}

Besides, once you learn to pass variables, references, or addresses, it becomes nicer than global variables anyway. It's more logical.

Dustin Dettmer said:

Multiple extern variables can be linked to a single 'real' variable.

Is it right to call them multiple extern variables? It's one variable made available to many files. I think.

Albin Engström said:

great

But I didn't say it... I think that was Dustin.

 1   2 


Go to: