forward declarations of structures throwing a redefinition error - struct

This code is compiling and functioning properly on a different environment in C using gcc. I am in the process of porting it into a new C++ environment using g++ and getting a redefinition error.
I've seen similar issues, but my problem might stem from the fact that I've got predeclarations in the struct definitions and need to predeclare again in the instantiation. Here is the relevant code:
transaction.h
...
typedef int ( *pfnTrans)(transaction *);
typedef struct tag_TRANSTEP transStep; //forward declare this for the following struct.
typedef struct tag_RETURNMAP
{
int onThisReturn;
transStep * runThis;
}returnMap;
#define MAX_BRANCHES 10
struct tag_TRANSTEP
{
pfnTrans thisStepsFunction;
returnMap retMap[MAX_BRANCHES];
};
...
source.cpp
...
//Forward declaring the steps, since they reference one another.
transStep tsConsultChoreList;
transStep tsPayBills;
transStep tsMowLawn;
transStep tsFixLawnMower;
transStep tsConsultChoreList = {fnConsultChoreList, {{MOW_LAWN, &tsMowLawn},
{PAY_BILLS, &tsPayBills},
{0, NULL}}}; // this entry signifies end of returnMap
transStep tsPayBills= {fnPayBills, {{SUCCESS, &fnConsultChoreList},
{0, NULL}}}; // this entry signifies end of returnMap
transStep tsMowLawn= {fnMowLawn, {{SUCCESS, &tsConsultChoreList},
{FIX_MOWER, &tsFixLawnMower},
{0, NULL}}}; // this entry signifies end of returnMap
transStep tsFixLawnMower= {fnFixLawnMower, {{SUCCESS, &tsMowLawn},
{0, NULL}}}; // this entry signifies end of returnMap
...
I'm not getting any errors from the .h file, but for each transStep in the .cpp I am getting a "redefinition of ..." error and an accompanying "... previously declared here" error.

That's legal in C? That's not legal in C++. If you prefix the "predeclarations" with extern thusly
extern transStep tsConsultChoreList;
extern transStep tsPayBills;
// etc...
it should work. In your .h file, you are predeclaring types, not instances of types. In your .cpp file, you're declaring actual instances, telling the compiler to allocate space for them. The extern keyword tells the compiler that the variable exists, just somewhere else. Then your declarations with initialization should work fine.

Related

Why I can't malloc function in between a code given below?? PS:- COMMENT LINES

why can't i declarer a new variable in the 4th linen using malloc function
compiler gives an error "Cannot create a new node".
while(a>0)
{ struct node*newnode=(struct node*)malloc(sizeof(struct node*));
printf("Enter the data in the node\n");
scanf("%d",&b);
struct node*newnodee=(struct node*)malloc(sizeof(struct node*));
newnode->data=b;
"#include studio.h>"
"#include stdlib.h>"
These library should be included in your files.

I am not able to link 2 .cpp files with a header in visual studio

I have a file p2.cpp and 2d.cpp which I'm trying to link with 2d.h.
I have included 2d.h in both .cpp files and I'm getting an error:
2d.obj : error LNK2005: "float (* v)[3]" (?v##3PAY02MA) already defined in p2.obj
1: fatal error LNK1169: one or more multiply defined symbols found.
What should I do?
I have a file p2.cpp and 2d.cpp which I'm trying to link with 2d.h. I
have included 2d.h in both .cpp files and I'm getting an error:
Each symbol may only be defined in a program once (refer One definition rule). I'm not sure what you're header file looks like, but typically this means something to the effect of defining something in you're header file that is included in more than one compilation unit. You could "extern" it in you're header, and ensure that it is defined in a separate compilation unite.
From the compiler error it looks like you've define an array of pointers to functions in your header file. Extern this and provide a single definition in a source file.
This code effectively causes the problem:
//--- Def.h
#ifndef DEF_H
#define DEF_H
float foo();
/*extern */float (*floatFunctionArray[3])();
#endif /* DEF_H */
//--- Def.cpp
#include "Def.h"
float foo()
{
return 0;
}
float (*floatFunctionArray[3])() =
{
foo, foo, foo
};
//--- main.cpp
#include "Def.h"
int
main(int argc, char** argv)
{
return 0;
}
Adding the commented out "extern" solves the issue.

C++ link error, symbol redefinition

I came across a problem recently.
I have three files, A.h, B.cpp, C.cpp:
A.h
#ifndef __A_H__
#define __A_H__
int M()
{
return 1;
}
#endif // __A_H__
B.cpp
#include "A.h"
C.cpp
#include "A.h"
As I comile the three files by MSVC, there is a error:
C.obj : error LNK2005: "int __cdecl M(void)" (?M##YAHXZ) already defined in B.obj
It is easy understanding, as we know, B.obj has a symbol named "M", also C.obj has a "M".
Here the error comes.
However, if I change M method to a class which contain a method M like this below:
A.h
#ifndef __A_H__
#define __A_H__
class CA
{
public:
int M()
{
return 1;
}
};
#endif // __A_H__
there is no more errors!! Could somebody tell me what is happening?
If B.cpp and C.cpp include A.h, then both are compiled with your definition of M, so both object files will contain code for M. When the linker gathers all the functions, he sees that M is defined in two object files and does not know which one to use. Thus the linker raises an LNK2005.
If you put your function M into a class declaration, then the compiler marks/handles M as an inline function. This information is written into the object file. The linker sees that both object files contain a definition for an inline version of CA::M, so he assumes that both are equal and picks up randomly one of the two definitions.
If you had written
class CA {
public:
int M();
};
int CA::M()
{
return 1;
}
this would have caused the same problems (LNK2005) as your initial version, because then CA::M would not have been inline any more.
So as you might guess by now, there are two solutions for you. If you want M to be inlined, then change your code to
__inline int M()
{
return 1;
}
If you don't care about inlining, then please do it the standard way and put the function declaration into the header file:
extern int M();
And put the function definition into a cpp file (for A.h this would ideally be A.cpp):
int M()
{
return 1;
}
Please note that the extern is not really necessary in the header file.
Another user suggested that you write
static int M()
{
return 1;
}
I'd not recommend this. This would mean that the compiler puts M into both of your object files and marks M as being a function that is only visible in each object file itself. If the linker sees that a function in B.cpp calls M, it finds M in B.obj and in C.obj. Both have M marked as static, so the linker ignores M in C.obj and picks the M from B.obj. Vice versa if a function in C.cpp calls M, the linker picks the M from C.obj. You will end up with multiple definitions of M, all with the same implementation. This is a waste of space.
See http://faculty.cs.niu.edu/~mcmahon/CS241/c241man/node90.html how to do ifdef guards. You have to start with ifndef before the define.
Edit: Ah no, while your guard is wrong that's not the issue. Put static in front of your function to make it work. Classes are different because they define types.
I don't know what's under the hood, but if you don't need a class I guess that the compiler will automatically add the "extern" key to your functions, so you'll get the error including the header 2 times.
You can add the static keyword to M() method so you'll have only one copy of that function in memory and no errors at compile time.
By the way: I see you have a #endif, but not a #ifdef or #ifndef, is it a copy/paste error?

sprintf (convert int to char[])

In my program I try to convert a int to a char[20];
I try to do this in the following way:
char str[20];
sprintf(str, "%d", timer);
in which timer is the int.
But when I build this code, I get the following warnings.
Type implicit declaration of function 'sprintf' [-Wimplicit-function-declaration]
incompatible implicit declaration of built-in function 'sprintf' [enabled by default]
what does that mean?
note:( I have included string.h and stdlib.h).
great, I added stdio.h to my code and now the warnings disappeared only to give me a even harder error.
undefined reference to `_sbrk'
You have to #include <stdio.h> to use sprintf()
you want to make sure you also add reference to stdio.h see this ref
You probably need to put sprintf(str, "%d", timer) inside a function (not on the global part of the source code).
Something like:
#include <stdlib.h>
char str[20];
// SPOT #1
int f() {
sprintf(str, "%d", timer); // this won't work if placed on SPOT #1
}

redefinition of default parameter error without redefining

I am getting a strange set of error in my Visual Studio 2010 compiler.
I am getting the errors of
error C2572: redefinition of default parameter
error C2011: 'class' type redefinition
I have checked thoroughly and I know very well that in the function definition, I have not given the default parameter values and I have given default parameter value only in function prototype in the header file.
Also, I am very much sure that no two class has been given the same class name.
Please can anybody tell me what could be the other reasons for getting these set of errors?
I have not got the exact reason why it was happening, but I have overcome it by using some simple techniques.
I used function overloading concept to avoid default parameter list. It will cause in duplication of code, but it has proved to be very effective.
So something like this
void myFunction( int, char * = '\0', char * = '\0' );
would become something like this
void myFunction( int );
void myFunction( int, char * );
void myFunction( int, char *, char * );
In this example, code is getting duplicated two times but it seems to be only work around solution.
Next, for the strange class type redefinition error, I was instantiating the class variable in many files. So, I removed that feature of instantiation everywhere and went with global variable something like this.
File named as myHeader.h
#include "myFile.h"
myClass myObj;
And in all the other files
#include "myHeader.h"
myObj.function1( );
myObj.function2( );

Resources