Is extern keyword really necessary? - c++

...
#include "test1.h"
int main(..)
{
count << aaa <<endl;
}
aaa is defined in test1.h,and I didn't use extern keyword,but still can reference aaa.
So I doubt is extern really necessary?

extern has its uses. But it mainly involves "global variables" which are frowned upon. The main idea behind extern is to declare things with external linkage. As such it's kind of the opposite of static. But external linkage is in many cases the default linkage so you don't need extern in those cases. Another use of extern is: It can turn definitions into declarations. Examples:
extern int i; // Declaration of i with external linkage
// (only tells the compiler about the existence of i)
int i; // Definition of i with external linkage
// (actually reserves memory, should not be in a header file)
const int f = 3; // Definition of f with internal linkage (due to const)
// (This applies to C++ only, not C. In C f would have
// external linkage.) In C++ it's perfectly fine to put
// somethibng like this into a header file.
extern const int g; // Declaration of g with external linkage
// could be placed into a header file
extern const int g = 3; // Definition of g with external linkage
// Not supposed to be in a header file
static int t; // Definition of t with internal linkage.
// may appear anywhere. Every translation unit that
// has a line like this has its very own t object.
You see, it's rather complicated. There are two orthogonal concepts: Linkage (external vs internal) and the matter of declaration vs definition. The extern keyword can affect both. With respect to linkage it's the opposite of static. But the meaning of static is also overloaded and -- depending on the context -- does or does not control linkage. The other thing it does is to control the life-time of objects ("static life-time"). But at global scope all variables already have a static life-time and some people thought it would be a good idea to recycle the keyword for controlling linkage (this is me just guessing).
Linkage basically is a property of an object or function declared/defined at "namespace scope". If it has internal linkage, it won't be directly accessible by name from other translation units. If it has external linkage, there shall be only one definition across all translation units (with exceptions, see one-definition-rule).

I've found the best way to organise your data is to follow two simple rules:
Only declare things in header files.
Define things in C (or cpp, but I'll just use C here for simplicity) files.
By declare, I mean notify the compiler that things exist, but don't allocate storage for them. This includes typedef, struct, extern and so on.
By define, I generally mean "allocate space for", like int and so on.
If you have a line like:
int aaa;
in a header file, every compilation unit (basically defined as an input stream to the compiler - the C file along with everything it brings in with #include, recursively) will get its own copy. That's going to cause problems if you link two object files together that have the same symbol defined (except under certain limited circumstances like const).
A better way to do this is to define that aaa variable in one of your C files and then put:
extern int aaa;
in your header file.
Note that if your header file is only included in one C file, this isn't a problem. But, in that case, I probably wouldn't even have a header file. Header files are, in my opinion, only for sharing things between compilation units.

If your test1.h has the definition of aaa and you wanted to include the header file into more than one translation unit you will run into multiple definition error, unless aaa is constant.
Better you define the aaa in a cpp file and add extern definition in header file that could be added to other files as header.
Thumb rule for having variable and constant in header file
extern int a ;//Data declarations
const float pi = 3.141593 ;//Constant definitions
Since constant have internal linkage in c++ any constant that is defined in a translation unit will not be visible to other translation unit, but it is not the case for variable they have external linkage i.e., they are visible to other translation unit. Putting the definition of a variable in a header, that is shared in other translation unit would lead to multiple definition of a variable, leading to multiple definition error.

In that case, extern is not necessary. Extern is needed when the symbol is declared in another compilation unit.
When you use the #include preprocessing directive, the included file is copied out in place of the directive. In this case you don't need extern because the compiler already know aaa.

If aaa is not defined in another compilation unit you don't need extern, otherwise you do.

Related

extern, linkage and global variables

In C++, say we have this header file:
myglobals.h
#ifndef my_globals_h
#define my_globals_h
int monthsInYear = 12;
#endif
and we include it in multiple implementation files, then we will get compilation errors since we end up with 'monthsInYear' defined multiple times, once in each file that monthsInYear is included in.
Fine. So if we modify our header and make our global const, like so:
const int monthsInYear = 12;
then our compilation errors go away. The explanation for this, as I understand it, and as given here for example, is that the const keyword here changes the linkage of monthsInYear to internal, which means that now each compilation unit that includes the header now has its own copy of the variable with internal linkage, hence we no longer have multiple definitions.
Now, an alternative would be to merely declare the variable in the header with extern, i.e.:
extern int monthsInYear;
and then define it in one of the implementation files that includes the header, i.e.:
#include "myglobals.h"
...
int monthsInYear = 12;
...
and then everywhere that includes it is dealing with one variable with external linkage.
This is fine, but the thing I'm a bit puzzled by is that using const gives it internal linkage, which fixes the problem, and using extern gives it external linkage, which also fixes the problem! It's like saying that any linkage will do, as long as we specify it. On top of that, when we just wrote:
int monthsInYear = 12;
wasn't the linkage already external? Which is why adding 'const' changed the linkage to internal?
It seems to me that the reason using 'extern' here actually fixes the problem isn't because it gives us external linkage (we already had that) but rather because it allows us to merely declare the variable without defining it, which we otherwise wouldn't be able to do, since:
int monthsInYear = 12;
both declares and defines it, and since including the header effectively copy-pastes the code into the implemenation file we end up with multiple definitions. Conversely, since extern allows us to merely declare it we end up with multiple declarations every time we include the header, which is fine since we're allowed to have multiple declarations, just not multiple definitions.
Is my understanding here correct? Sorry if this is massively obvious, but it seems that extern does at least three things:
specifies external linkage
allows declaration of objects without defining them
specifies static storage duration
but a lot of sources I look at don't make this clear, and when talking about using extern to stop 'multiple definition' errors with global variables don't make it clear that the key thing is separating the declaration from the definition.
For a non-const variable, extern has the effect of specifying that the variable has external linkage (which is the default), but it also converts the definition into a declaration if there's no initializer - i.e. extern int i; does not actually define i. (extern int i = 5; would, and would hopefully generate a compiler warning).
When you write extern int monthsInYear; in multiple source files (or #include it into them, which is equivalent), none of them define it. int monthsInYear = 12; defines the variable in that source file only.
The storage class specifiers are a part of the decl-specifier-seq of a declaration syntax. They control two independent properties of the names introduced by the declaration: their storage duration and their linkage.
extern - static or thread storage duration and external linkage
This is what cppreference says which matches your understanding perfectly.

Why is it that I can include a header file in multiple cpp files that contains const int and not have a compiler error?

Let's assume that I have files a.cpp b.cpp and file c.h. Both of the cpp files include the c.h file. The header file contains a bunch of const int definitions and when I compile them I get no errors and yet I can access those const as if they were global variables. So the question, why don't I get any compilation errors if I have multiple const definitions as well as these const int's having global-like scope?
This is because a const declaration at namespace scope implies internal linkage. An object with internal linkage is only available within the translation unit in which it is defined. So in a sense, the one const object you have in c.h is actually two different objects, one internal to a.cpp and one internal to b.cpp.
In other words,
const int x = ...;
is equivalent to
static const int x = ...;
while
int x;
is similar to
extern int x;
because non-const declarations at namespace scope imply external linkage. (In this last case, they aren't actually equivalent. extern, as well as explicitly specifying external linkage, produces a declaration, not a definition, of an object.)
Note that this is specific to C++. In C, const doesn't change the implied linkage. The reason for this is that the C++ committee wanted you to be able to write
const int x = 5;
in a header. In C, that header included from multiple files would cause linker errors, because you'd be defining the same object multiple times.
From the current C++ standard...
7.1.1 Storage class specifiers
7) A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration and provided it is not declared const. Objects declared const and not explicitly declared extern have internal linkage.
3.5 Program and Linkage
2) When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
The preprocessor causes stuff defined in headers to be included in the current translation unit.
When you do so, you create a separate const variable in each object file for every constant in the header. It's not a problem, since they are const.
Real reason: because #define is evil and needs to die.
Some usages of #define can be replaced with inline functions. Some - with const variable declarations. Since #define tends to be in header files, replacing those with consts in place better work. Thus, the "consts are static by default" rule.

Use of "extern" storage class specifier in C

How does the following example usage of extern specifer behave.
We have a global variable int x both in files one.c and two.c
We want to use these in three.c so have declared this variable in three.c as
extern int x;
What would happen when we compile and link these files?
My answer is: compilation of all these files should succeed, however the linker should flag an error at linking, due to multiple declarations of x.
Would there be any difference in behavior in C++ ?
Is these any way to refer to int x (in three.c) simultaneously from both files, in C and C++.
In C++, I guess we can use namespaces to acheive this. Right?
By default, global variables have external linkage, which means that they can be used by other source files (or "translation units"). If you instead declare your global variables with the static keyword, they will have internal linkage, meaning they will not be usable by other source files.
For variables with external linkage, you can't have multiple variables with the same name, or the linker will complain. You can have two variables with the same name, though, as long as at least one has internal linkage, and of course you can't reference both of them in the same source file.
An extern declaration is just saying to the compiler "here is the name of some variable with external linkage defined in another translation unit," allowing you to refer to that variable.
C++ is exactly the same, except for the addition of namespaces. If global variables are put inside a namespace, then they can have the same name without linker errors, provided they are in different namespaces. Of course, all references to those variables then have to either refer to the full name namespace::var_name, or use a using declaration to establish a local namespace context.
C++ also has anonymous namespaces, which are entirely equivalent to using the static keyword for global variables in C: all variables and functions declared inside an anonymous namespace have internal linkage.
So, to answer your original question, you are right -- compilation would succeed, but linking would fail, due to multiple definitions of the variable x with external linkage (specifically, from the translation units one.c and two.c).
From three.c, there is no way to refer simultaneously to both variables x. You'll need to rename x in one or both modules, or switch to C++ and put at least one x inside a namespace.
In C, you could do this:
// one.c
static int x;
int *one_x = &x;
// two.c
static int x;
int *two_x = &x;
// three.c
extern int *one_x;
extern int *two_x;
Now you can refer unambiguously to the x in file one.c or the x in file two.c from the file three.c.
However, this might be a bit more effort than it's worth. Perhaps you should be coming up with more descriptive names for your global variables instead of toying around with theoretical ways to circumvent C's single global namespace.
To avoid generating duplicate symbols, you should declare extern int x; in a single header file (a .h file), and then have all .c files which will use x #include that header file, and define or initialize int x; in one of the .c files.
You might be interested by the answers to this question.
Summary: the linker may or may not fail to link the file. It depends on the initialization of the variable. It will definitely fail if the variable has different initializations in different files.
Remember that you can NOT extern a global static variable.. !!

What is external linkage and internal linkage?

I want to understand the external linkage and internal linkage and their difference.
I also want to know the meaning of
const variables internally link by default unless otherwise declared as extern.
When you write an implementation file (.cpp, .cxx, etc) your compiler generates a translation unit. This is the source file from your implementation plus all the headers you #included in it.
Internal linkage refers to everything only in scope of a translation unit.
External linkage refers to things that exist beyond a particular translation unit. In other words, accessible through the whole program, which is the combination of all translation units (or object files).
As dudewat said external linkage means the symbol (function or global variable) is accessible throughout your program and internal linkage means that it is only accessible in one translation unit.
You can explicitly control the linkage of a symbol by using the extern and static keywords. If the linkage is not specified then the default linkage is extern (external linkage) for non-const symbols and static (internal linkage) for const symbols.
// In namespace scope or global scope.
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static
// The same goes for functions (but there are no const functions).
int f(); // extern by default
static int sf(); // explicitly static
Note that instead of using static (internal linkage), it is better to use anonymous namespaces into which you can also put classes. Though they allow extern linkage, anonymous namespaces are unreachable from other translation units, making linkage effectively static.
namespace {
int i; // extern by default but unreachable from other translation units
class C; // extern by default but unreachable from other translation units
}
A global variable has external linkage by default. Its scope can be extended to files other than containing it by giving a matching extern declaration in the other file.
The scope of a global variable can be restricted to the file containing its declaration by prefixing the declaration with the keyword static. Such variables are said to have internal linkage.
Consider following example:
1.cpp
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
The signature of function f declares f as a function with external linkage (default). Its definition must be provided later in this file or in other translation unit (given below).
max is defined as an integer constant. The default linkage for constants is internal. Its linkage is changed to external with the keyword extern. So now max can be accessed in other files.
n is defined as an integer variable. The default linkage for variables defined outside function bodies is external.
2.cpp
#include <iostream>
using namespace std;
extern const int max;
extern int n;
static float z = 0.0;
void f(int i)
{
static int nCall = 0;
int a;
//...
nCall++;
n++;
//...
a = max * z;
//...
cout << "f() called " << nCall << " times." << endl;
}
max is declared to have external linkage. A matching definition for max (with external linkage) must appear in some file. (As in 1.cpp)
n is declared to have external linkage.
z is defined as a global variable with internal linkage.
The definition of nCall specifies nCall to be a variable that retains its value across calls to function f(). Unlike local variables with the default auto storage class, nCall will be initialized only once at the first invocation of f(). The storage class specifier static affects the lifetime of the local variable and not its scope.
NB: The keyword static plays a double role. When used in the definitions of global variables, it specifies internal linkage. When used in the definitions of the local variables, it specifies that the lifetime of the variable is going to be the duration of the program instead of being the duration of the function.
In terms of 'C' (Because static keyword has different meaning between 'C' & 'C++')
Lets talk about different scope in 'C'
SCOPE: It is basically how long can I see something and how far.
Local variable : Scope is only inside a function. It resides in the STACK area of RAM.
Which means that every time a function gets called all the variables
that are the part of that function, including function arguments are
freshly created and are destroyed once the control goes out of the
function. (Because the stack is flushed every time function returns)
Static variable: Scope of this is for a file. It is accessible every where in the file
in which it is declared. It resides in the DATA segment of RAM. Since
this can only be accessed inside a file and hence INTERNAL linkage. Any
other files cannot see this variable. In fact STATIC keyword is the
only way in which we can introduce some level of data or function
hiding in 'C'
Global variable: Scope of this is for an entire application. It is accessible form every
where of the application. Global variables also resides in DATA segment
Since it can be accessed every where in the application and hence
EXTERNAL Linkage
By default all functions are global. In case, if you need to
hide some functions in a file from outside, you can prefix the static
keyword to the function. :-)
Before talking about the question, it is better to know the term translation unit, program and some basic concepts of C++ (actually linkage is one of them in general) precisely. You will also have to know what is a scope.
I will emphasize some key points, esp. those missing in previous answers.
Linkage is a property of a name, which is introduced by a declaration. Different names can denote same entity (typically, an object or a function). So talking about linkage of an entity is usually nonsense, unless you are sure that the entity will only be referred by the unique name from some specific declarations (usually one declaration, though).
Note an object is an entity, but a variable is not. While talking about the linkage of a variable, actually the name of the denoted entity (which is introduced by a specific declaration) is concerned. The linkage of the name is in one of the three: no linkage, internal linkage or external linkage.
Different translation units can share the same declaration by header/source file (yes, it is the standard's wording) inclusion. So you may refer the same name in different translation units. If the name declared has external linkage, the identity of the entity referred by the name is also shared. If the name declared has internal linkage, the same name in different translation units denotes different entities, but you can refer the entity in different scopes of the same translation unit. If the name has no linkage, you simply cannot refer the entity from other scopes.
(Oops... I found what I have typed was somewhat just repeating the standard wording ...)
There are also some other confusing points which are not covered by the language specification.
Visibility (of a name). It is also a property of declared name, but with a meaning different to linkage.
Visibility (of a side effect). This is not related to this topic.
Visibility (of a symbol). This notion can be used by actual implementations. In such implementations, a symbol with specific visibility in object (binary) code is usually the target mapped from the entity definition whose names having the same specific linkage in the source (C++) code. However, it is usually not guaranteed one-to-one. For example, a symbol in a dynamic library image can be specified only shared in that image internally from source code (involved with some extensions, typically, __attribute__ or __declspec) or compiler options, and the image is not the whole program or the object file translated from a translation unit, thus no standard concept can describe it accurately. Since symbol is not a normative term in C++, it is only an implementation detail, even though the related extensions of dialects may have been widely adopted.
Accessibility. In C++, this is usually about property of class members or base classes, which is again a different concept unrelated to the topic.
Global. In C++, "global" refers something of global namespace or global namespace scope. The latter is roughly equivalent to file scope in the C language. Both in C and C++, the linkage has nothing to do with scope, although scope (like linkage) is also tightly concerned with an identifier (in C) or a name (in C++) introduced by some declaration.
The linkage rule of namespace scope const variable is something special (and particularly different to the const object declared in file scope in C language which also has the concept of linkage of identifiers). Since ODR is enforced by C++, it is important to keep no more than one definition of the same variable or function occurred in the whole program except for inline functions. If there is no such special rule of const, a simplest declaration of const variable with initializers (e.g. = xxx) in a header or a source file (often a "header file") included by multiple translation units (or included by one translation unit more than once, though rarely) in a program will violate ODR, which makes to use const variable as replacement of some object-like macros impossible.
I think Internal and External Linkage in C++ gives a clear and concise explanation:
A translation unit refers to an implementation (.c/.cpp) file and all
header (.h/.hpp) files it includes. If an object or function inside
such a translation unit has internal linkage, then that specific
symbol is only visible to the linker within that translation unit. If
an object or function has external linkage, the linker can also see it
when processing other translation units. The static keyword, when used
in the global namespace, forces a symbol to have internal linkage. The
extern keyword results in a symbol having external linkage.
The compiler defaults the linkage of symbols such that:
Non-const global variables have external linkage by default
Const global variables have internal linkage by default
Functions have external linkage by default
Basically
extern linkage variable is visible in all files
internal linkage variable is visible in single file.
Explain: const variables internally link by default unless otherwise declared as extern
by default, global variable is external linkage
but, const global variable is internal linkage
extra, extern const global variable is external linkage
A pretty good material about linkage in C++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
Linkage determines whether identifiers that have identical names refer to the same object, function, or other entity, even if those identifiers appear in different translation units. The linkage of an identifier depends on how it was declared.
There are three types of linkages:
Internal linkage : identifiers can only be seen within a translation unit.
External linkage : identifiers can be seen (and referred to) in other translation units.
No linkage : identifiers can only be seen in the scope in which they are defined.
Linkage does not affect scoping
C++ only : You can also have linkage between C++ and non-C++ code fragments, which is called language linkage.
Source :IBM Program Linkage
In C++
Any variable at file scope and that is not nested inside a class or function, is visible throughout all translation units in a program. This is called external linkage because at link time the name is visible to the linker everywhere, external to that translation unit.
Global variables and ordinary functions have external linkage.
Static object or function name at file scope is local to translation unit. That is
called as Internal Linkage
Linkage refers only to elements that have addresses at link/load time; thus, class declarations and local variables have no linkage.

Header Guards and LNK4006

I have a character array defined in a header
//header.h
const char* temp[] = {"JeffSter"};
The header if #defined guarded and has a #pragma once at the top. If this header is included in multiple places, I get an LNK4006 - char const * * temp already defined in blahblah.obj. So, I have a couple of questions about this
Why does this happen if I have the guards in place? I thought that they prevented the header from being read in after the first access.
Why do the numerous enums in this header not also give the LNK4006 warnings?
If I add static before the signature, I don't get the warning. What are the implications of doing it this way.
Is there a better way to do this that avoids the error, but lets me declare the array in the header. I would really hate to have a cpp file just for an array definition.
Why does this happen if I have the guards in place? I thought that they prevented the header from being read in after the first access.
Include guards make sure that a header is included only once in one file (translation unit). For multiple files including the header, you want the header to be included in each file.
By defining, as opposed to declaring variables with external linkage (global variables) in your header file, you can only include the header in once source file. If you include the header in multiple source files, there will be multiple definitions of a variable, which is not allowed in C++.
So, as you have found out, it is a bad idea to define variables in a header file for precisely the reason above.
Why do the numerous enums in this header not also give the LNK4006 warnings?
Because, they don't define "global variables", they're only declarations about types, etc. They don't reserve any storage.
If I add static before the signature, I don't get the warning. What are the implications of doing it this way.
When you make a variable static, it has static scope. The object is not visible outside of the translation unit (file) in which it is defined. So, in simple terms, if you have:
static int i;
in your header, each source file in which you include the header will get a separate int variable i, which is invisible outside of the source file. This is known as internal linkage.
Is there a better way to do this that avoids the error, but lets me declare the array in the header. I would really hate to have a cpp file just for an array definition.
If you want the array to be one object visible from all your C++ files, you should do:
extern int array[SIZE];
in your header file, and then include the header file in all the C++ source files that need the variable array. In one of the source (.cpp) files, you need to define array:
int array[SIZE];
You should include the header in the above source file as well, to allow for catching mistakes due to a difference in the header and the source file.
Basically, extern tells the compiler that "array is defined somewhere, and has the type int, and size SIZE". Then, you actually define array only once. At link stage, everything resolves nicely.
Include guards protect you from including the same header into the same file repeatedly - but not from including it in distinct files.
What happens is that the linker sees temp in more then one object file - you can solve that by making temp static or putting it into an unnamed namespace:
static const char* temp1[] = {"JeffSter"};
// or
namespace {
const char* temp2[] = {"JeffSter"};
}
Alternatively you can use one source file which defines temp and just declare it as extern in the header:
// temp.cpp:
const char* temp[] = {"JeffSter"};
// header.h:
extern const char* temp[];
Header guards have absolutely nothing to do with preventing multiple definitions in your entire program. The purpose of header guards is to prevent multiple inclusion of the same header file into the same translation unit (.cpp file). In other words, they exist to prevent multiple definitions in the same source file. And they do work as intended in your case.
The rule that governs multiple-definition issues in C++ is called One Definition Rule (ODR). ODR is defined differently for different kinds of entities. For example, types are allowed to have multiple identical definitions in the program. They can (and most always have to) be defined in every translation unit where they are used. This is why your enum definition does not result in an error.
Objects with external linkage are a completely different story. They have to be defined in one and only one translation unit. This is why your definition of temp causes an error when you include the header file into multiple translation units. Include guards can't prevent this error. Just don't define objects with external linkage in header files.
By adding static you give your object internal linkage. This will make the error disappear, since now it is perfectly OK from ODR point of view. But this will define an independent temp object in each translation unit into which your header file is included. To achieve the same effect you could also do
const char* const temp[] = { "JeffSter" };
since const objects in C++ have internal linkage by default.
This depends on whether you need an object with external linkage (i.e. one for the entire program) or an object with internal linkage (unique to each translation unit). If you need the latter, use static and/or extra const (if that works for you) as shown above.
If you need the former (external linkage), you should put a non-defining declaration into the header file
extern const char* temp[];
and move the definition into one and only one .cpp file
char* const temp[] = { "JeffSter" };
The above declaration in the header file will work for most purposes. However, it declares temp as an array of unknown size - an incomplete type. If you wish to declare it as an array of known size, you have to specify the size manually
extern const char* temp[1];
and remember to keep it in-synch between the declaration and definition.
I respectfully disagree with the advice against defining variables in headers, because I think "never" is too broad. Nevertheless, the episode that brought me to this thread offers a cautionary tale for those who dare to do so.
I landed on this page as the result of an inquiry into the cause of warning LNK4006, calling out a long established array that I just moved from the translation unit that defines my DLLMain routine into the private header that is included in most of the translation units that comprise this library. I have compiled this library hundreds of times over the last 11 years, and I had never before seen this warning.
Shortly after I read this page, I discovered the cause of the error, which was that the definition was outside the guard block that protects everything else that is defined in the module that also defines DLLMain, which is where I usually gather all the memory blocks that need external linkage. As expected, moving the table inside the guard block eliminated the warnings, leaving me with only two, related to a brand new externally linked table, to be resolved.
Takeaway: You can define variables in headers, and it's a great place to put common blocks, but mind your guards.
Hang on... you are mixing up your declarations...you did say 'char const * * temp' yet in your header file you have 'const char* temp[] = {"JeffSter"};'.
See section 6.1 of the C FAQ, under 'Section 6. Arrays and Pointers', to quote:
6.1: I had the definition char a[6] in one source file, and in
another I declared extern char *a. Why didn't it work?
A: In one source file you defined an array of characters and in the
other you declared a pointer to characters. The declaration
extern char *a simply does not match the actual definition.
The type pointer-to-type-T is not the same as array-of-type-T.
Use extern char a[].
References: ISO Sec. 6.5.4.2; CT&P Sec. 3.3 pp. 33-4, Sec. 4.5
pp. 64-5.
That is the source of the problem. Match up your declaration and definitions. Sorry if this sounds blunt, but I could not help noticing what the linker was telling you...