Hello! I'm new to the forum and still in the process of learning C++. I'm learning C++ with "Teach Yourself C++ in 21 days" from Sams publishing. I'm on day 18 so i'm almost finished! :)
But I've hit a snag. My book did an unusually poor job of explaining the idea of internal and external linkage. I've been reading different articles on the internet about the subject, but disagreement between the different articles, as well as with what my compiler does, has left me pretty confused.
The extern keyword, according to one article, tells the compiler that the variable or function here, is declared in some other source file, and we'll be acccesing it in this source file. Whereas my book seems to say that declaring a variable external, tells the compiler that it can be accessed by other source files. Kind of a big difference there.
Another article states, that if you were to create a header file, say file1.h which contained a variable declaration, such as 'int someInt;' and included this at the top of two source files, the linker wouldn't know if the two instances of that variable were supposed to be the same or different, and would complain of ambiguity.
Well that appears to be incorrect, because when I declare 'int someInt' in a header file, and create two source files that use it, the linker does not complain of ambiguity, and experimenting has shown two instances of the variable exist.
Can anyone explain to me whats going on?
I think one of the biggest reasons I'm having trouble understanding this is I don't know how you could or would use more than one source file in the same program. Only one source file containing main() is allowed, and things in the other source file are generally hidden from the main source file. I don't see the point!
Paul McKenzie
February 17th, 2008, 02:30 PM
Hello! I'm new to the forum and still in the process of learning C++. I'm learning C++ with "Teach Yourself C++ in 21 days" from Sams publishing. I'm on day 18 so i'm almost finished! :)You may be finished with the book, but you won't be finished learning C++. You can't learn this language in 21 days, plain and simple.
Another article states, that if you were to create a header file, say file1.h which contained a variable declaration, such as 'int someInt;' and included this at the top of two source files, the linker wouldn't know if the two instances of that variable were supposed to be the same or different, and would complain of ambiguity. That is correct.
Well that appears to be incorrect, because when I declare 'int someInt' in a header file, and create two source files that use it, the linker does not complain of ambiguity, and experimenting has shown two instances of the variable exist. Your test is flawed or you did something wrong, or your compiler/linker is broken.
You don't need header files to prove this. Declare a global variable of the same name in two different source files. You get the error:
File1.cpp
int x;
void foo(int);
int main()
{
x = 10;
foo(x);
}
File2.cpp
#include <iostream>
int x;
void foo(int a)
{
std::cout << a;
}
Compile both of these as seperate modules. The linker will give an error that "x" has been declared multiple times causing a linker error.
I think one of the biggest reasons I'm having trouble understanding this is I don't know how you could or would use more than one source file in the same program.When you get to write professional applications that consist of hundreds, maybe thousands of functions, then you will see why breaking up the program into seperate modules makes sense. I currently maintain an application that has over 200 seperate modules. Toy programs do not need, or usually do not need multiple modules.
Regards,
Paul McKenzie
Mikau
February 17th, 2008, 02:53 PM
Thanks for the speedy and detailed reply, Paul McKenzie!
first of all, while I agree you can't learn C++ in 21 days, the book is over 900 pages! :P its divided into 21 chapters, each of which could, conceivably be read in one day, but you'd never be able to grasp and understand it that quickly. Its just a marketing statement which is technically correct, but practically wrong. 21 weeks is more like how long it would take to get through this book. And from what I hear, you can never know all there is to know about C++.
Anyway, I pasted in your code to two separate .cpp files as shown, and compiled. It did not complain, as you said it should, but I noticed this message in the build information text field:
Warning: Public symbol '_x' defined in both module C:\DOCUMENTS AND SETTINGS\RAV\CBPROJECT\EXTERNALVARIABLES\WINDOWS\DEBUG_BUILD\FILE1.OBJ and C:\DOCUMENTS AND SETTINGS\RAV\CBPROJECT\EXTERNALVARIABLES\WINDOWS\DEBUG_BUILD\FILE2.OBJ
so maybe my compiler just posts a warning?
Another thing I'm wondering, you said to compile them as separate modules. I'm not sure if I'm doing that specifically. In my IDE, I added two source files to the project, and pressed the IDE's compile button. So I'm not sure if it compiled them as separate modules, as you said, or if it somehow put them together first.
Paul McKenzie
February 17th, 2008, 03:06 PM
Thanks for the speedy and detailed reply, Paul McKenzie!
first of all, while I agree you can't learn C++ in 21 days, the book is over 900 pages!I have two books alone, just on the standard library and another on C++ streams, that are over 1700 pages -- and that is just two topics.
Anyway, I pasted in your code to two separate .cpp files as shown, and compiled. It did not complain, as you said it should, but I noticed this message in the build information text field:Some linkers will allow you to use multiply-defined variables (and functions), but will only take the first one that they see. There may be a linker switch that will force your linker to generate an error.
In one module you can declare this globally:
int x;
While in another you can have this:
float x;
What happens when you link these two together? That's up to the linker -- most will give you an error, some will give you a warning, some will happily not warn you and take the one that it feels like taking. The problem is that overall, the program will be ill-formed and ambiguous (if the linker allows you to create the program).
so maybe my compiler just posts a warning? The compiler is not involved here. It is the linker that is responsible for resolving these things. So it is your linker that is giving you the warning.
Another thing I'm wondering, you said to compile them as separate modules. I'm not sure if I'm doing that specifically. In my IDE, I added two source files to the project, and pressed the IDE's compile button. So I'm not sure if it compiled them as separate modules, as you said, or if it somehow put them together first.It sounds like you are doing it correctly. You will know if you've created two files with .obj extensions
Regards,
Paul McKenzie
Mikau
February 17th, 2008, 03:16 PM
but I also read that variables and functions declared with file scope are external by default. Aren't those variables at file scope?
I have two books alone, just on the standard library and another on C++ streams, that are over 1700 pages -- and that is just two topics.
lol! oooh thats depressing! :(
Paul McKenzie
February 17th, 2008, 03:39 PM
but I also read that variables and functions declared with file scope are external by default. Aren't those variables at file scope?Yes, they are at file scope. This doesn't take away from the fact that the linker needs to see only one non-extern declaration for it not to complain.
In general, avoid using external variables in C++ programs.
Regards,
Paul McKenzie
Lindley
February 17th, 2008, 04:02 PM
I think one of the biggest reasons I'm having trouble understanding this is I don't know how you could or would use more than one source file in the same program. Only one source file containing main() is allowed, and things in the other source file are generally hidden from the main source file. I don't see the point!
This isn't immediately clear to many people, so it really should be laid out plainly.
This is the reason why .h files exist.
See, if a function is declared somewhere other than the file containing main(), the contents of the function doesn't have to be known to main----only the way in which the function should be called, and what it will return. main() doesn't care about anything else. Nor does any function care about the inner workings of any other, in an ideally-designed program. While code may be written which relies on function side-effects (state changes not reflected in the arguments or return value) to be correct, the compiler fundamentally does not care.
Therefore, the file containing main() only needs to #include the .h file to compile. In order to link the program into an executable---a completely independent build step---another file must also be compiled which contains the definition of every function actually used in main() (or in a function called from main()).
The compile step just needs to know, "This is what the function looks like from the outside." Only the linker step needs to know how it actually works.
The exception to this is templates. In order for templated code to compile, the definitions must be visible to any code trying to use them. Sometimes this means doing a "#include "whatever.cpp"" at the end of whatever.h; sometimes it means you'll see headers that end in .hpp, or have no extension at all (as with the standard headers). This weirdness is one reason why some people consider the template system to be fundamentally broken, even if it does make a few things easier.
Mikau
February 17th, 2008, 09:28 PM
ahh.. sweet information! Thanks lindley! But now i'm wondering... okay the header file basically assures the main source file that these functions are defined somewhere else, and thus can be called, but how does the linker know where to find the definitions? Doesn't the definition code need to be supplied somewhere?
And to Paul McKinzey
This doesn't take away from the fact that the linker needs to see only one non-extern declaration for it not to complain.
that SOUNDS right, but it disagrees with something both my compiler and book said, namely constants. They said constants are internal by default (whatever exactly that means) and if wanted to make them accessible outside the source, you have to do the following:
here there is no nonexternal declaration, as you say. But the linker does not complain, furthermore this is how my book says to make constants external. The extern keyword goes before both of them.
Lindley
February 18th, 2008, 07:20 AM
ahh.. sweet information! Thanks lindley! But now i'm wondering... okay the header file basically assures the main source file that these functions are defined somewhere else, and thus can be called, but how does the linker know where to find the definitions? Doesn't the definition code need to be supplied somewhere?
If you're using a command-line compiler/linker such as gcc or g++, you simply specify all the relevant source files at once. It can figure things out from there.
If you're using an IDE like Visual Studio or XCode, you simply add all source files (or 3rd party libraries, which may also contain definitions!) to the project.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.