|
I tried to isolate the problem
It appears when a global variable is declared at the .h header file and the header file is called from 2 or more cpp files, as example I tried to link the following 3 files:
#pragma once
#include <stdio.h>
int variable;
#include "header.h"
void main()
{
variable=0;
}
#include "header.h"
void change()
{
variable=0;
}
Then the following LINKER error appear:
1>source2.obj : error LNK2005: redefined "int variable" (?variable@@3HA) in main.obj
The only way I could "fix" the problem is in project properties> linker>command line add:
/FORCE:MULTIPLE
Unfortunately it can hide possible problems
I think the problem is that the #pragma once does not work.
It does not work also to define a constant and use #ifndef to avoid reading 2 times.
|
|
|
|
|
You should declare it extern in the header, and define it in only one of your .cpp
files. Something like:
#pragma once
#include <stdio.h>
extern int variable;
#include "header.h"
int variable = 0;
void main()
{
}
|
|
|
|
|
It works!
It must be "declared" as extern in the header file one time and "defined" one time as you said in the main.cpp.
It must not be defined again at any other file (source.cpp) unless extern is added
The dafault value must be placed in the main.cpp as you wrote
I do not like the solution very much because I have to be careful when changing the name of the variable to do in both sides.
|
|
|
|
|
Member 11988283 wrote: It must not be defined again at any other file (source.cpp) unless extern is added You do not need to do that, as it is declared in the header.
Member 11988283 wrote: I do not like the solution very much because ... Sorry, but you have no choice if you want to use global variables; which is something you should really avoid.
|
|
|
|
|
I tried it by delete from the .cpp but unfortunately following error appeared:
error LNK2001: external symbol "int variable" (?variable@@3HA) unresolved
I agree with you, there is not other choice. I do not like also global variables so I had not that problem before 
|
|
|
|
|
Member 11988283 wrote: I tried it by delete from the .cpp Why? I showed you what to do and explained where it should be declared: in the header. And where it should be defined: in one .cpp file.
|
|
|
|
|
Another way to solve this problem (and have only one place where the variable is defined):
In foo.h:
#ifdef DEFINE_GLOBALS
#define GLOBAL
#define INIT(x) = (x)
#else
#define GLOBAL extern
#define INIT(x)
#endif
GLOBAL int globalInt INIT(42);
In foo.cpp (and ONLY in foo.cpp):
#define DEFINE_GLOBALS
#include "foo.h"
In other source files:
#include "foo.h"
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack.
--Winston Churchill
|
|
|
|
|
I don't see the advantage of this over the usual approach (the one suggested by Richard).
|
|
|
|
|
The problem with this is that everything is hidden by those #define s so as to make it less easy to understand when looking at the source code.
|
|
|
|
|
It can be confusing if encountered for the first time, but if this is the agreed idiom in your team, it ensures that all definitions occur only once. This in turn eliminates all possibilities of mismatches between declarations and definitions.
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack.
--Winston Churchill
|
|
|
|
|
The basis for the error is that building an EXE constitutes compiling and linking.
Compilation - Every CPP file, also called a translation unit or compilation unit, is compiled separately to form OBJ files.
Linking - All the OBJ files are linked together to become the EXE.
In your case, during compilation, every OBJ file will contain a symbol called int variable .
This means the compilation of all units are successful.
But when the linker takes all the OBJ files to create an EXE, it finds the same symbol in all translation units and so it becomes ambiguous to it as to which symbol to use.
Having said this, there are two things that you may want to do with global variables.
First
You may want to use a global variable that is shared between all translation units.
This is the answer that you've gotten so far.
The global variable declaration must happen only once so that the linker only finds one symbol for the variable and links all other extern references to that symbol.
Second
You may want to use the same name for the global variable in each translation unit.
For this to happen, declare the global variable as static - static int variable;
This forces the compilation process to not share the symbol among other translation units.
For more information refer to this link - Types of Linkage[^]
«_Superman_»
I love work. It gives me something to do between weekends.
Microsoft MVP (Visual C++) (October 2009 - September 2013) Polymorphism in C
|
|
|
|
|
«_Superman_» wrote: For this to happen, declare the global variable as static - static int variable; Which means they are not global.
|
|
|
|
|
They are definitely not local.
They are global to the functions in that file.
They are local to that file.
If you look at the assembly output, they are created as global variables.
«_Superman_»
I love work. It gives me something to do between weekends.
Microsoft MVP (Visual C++) (October 2009 - September 2013) Polymorphism in C
|
|
|
|
|
«_Superman_» wrote: They are definitely not local. Yes they are; go back to the link in your original post and read it again.
«_Superman_» wrote: They are global to the functions in that file. The term 'global' here is confusing the issue.
«_Superman_» wrote: They are local to that file. So which is it?
«_Superman_» wrote: If you look at the assembly output, they are created as global variables. Again you misunderstand the term 'global'.
|
|
|
|
|
It is a global variable with file scope.
«_Superman_»
I love work. It gives me something to do between weekends.
Microsoft MVP (Visual C++) (October 2009 - September 2013) Polymorphism in C
|
|
|
|
|
It is not "global"; You are just confusing the issue by saying that.
|
|
|
|
|
what is the use of "%%" meaning in c language? and where will we use?give me a small exapmle?
|
|
|
|
|
Used with printf() if you want to print a percent sign.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
The code below uses a variable's type as size in malloc(). And I printf the size of //line 1, b and c to find out their sizes malloc will allocation the space for them in heap.
Question part 1:
One person told me I should use // line a's size to malloc in // #####, while the other person said I should use //line c instead. They do have the same size in printf(). Which one is correct? Why?
Question part 2:
// line b and // line c both have the same type of variable pointers, but why do they have different sizes?
struct Vector {
double *data;
size_t size;
};
int main()
{ int a, b, d;
int sz = 12;
a = sizeof(struct Vector); // line a
printf("%d\n", a); //a = 16
b = sizeof(struct Vector*); // line b
printf("%d\n", b); //b = 8
c = sizeof(*retVal); // line c
printf("%d\n\n", c); //c = 16
struct Vector *retVal = malloc (sizeof (struct Vector)); //#####
retVal->data = malloc (sz * sizeof (double));
// Set size and return.
retVal->size = sz;
printf("retVal->size: %d\n", sz);
return 0;
}
Thank you for your help. 
|
|
|
|
|
Both are correct. sizeof(struct Vector) expands to the size of the type while sizeof(*retVal) expands to the size of the type pointed to by the variable.
The second method should be preferred because it will be always the correct size even when changing the variable type. Imagine that you have another structure with different size. When you now change the type of retVal to that structure, you must also change the type for the first sizeof() but not for the second.
|
|
|
|
|
Thanks for your response. Just to make sure I understand your answer, I listed .....I'm thinking the second malloc() used in my previous example can be replaced by the line below?
sizeof(12 * sizeof(retVal->data));
Thank you!
|
|
|
|
|
No, that is wrong. The second example from your initial post (sizeof(struct Vector*) ) returns the size of a pointer which is 4 or 8 with 32-bit or 64-bit builds.
The sizeof[^] operator expands to the size of the argument during compilation. If the argument is not a type but a variable, the type of the variable is returned. If the variable is a pointer, the pointer must be dereferenced using the * operator to get the size of the type instead the size of the pointer. Similar applies when the type is a pointer itself.
But when passing a type followed by * like in your second example, it is a pointer to the type. In that case the type does not care because all pointers have the same size.
Maybe you are irritated how the * operator is treated. With declarations it indicates a pointer. When accessing variables, it accesses the content of pointer variables.
|
|
|
|
|
Thank you for clarifying my confusion, Jochen!! I appreciate it.
|
|
|
|
|
Jochen provided a more complete answer.
modified 21-Nov-15 6:54am.
|
|
|
|
|
I have a single doc multiple views app in a tabbed view type mainframe. I have printing working nicely for each view on its own, but I need to print all views in one 'report'. I started by adding a "Print All" command in CMainFrame , and then traversing all document views (as CView pointers), but it gets very messy for a few reasons:
- each view must be cast to its RUNTIME_CLASS and checked to find which it is, so that its OnPrint function can be called
- each view has different scaling, so a single CPrintInfo won't suffice
- its not known in advance how many pages to set, but this can be overcome with m_bContinue checks.
Any suggestions on how to print a single document multiple views please?
Thanks!
|
|
|
|