Ok guys, what is the deal!? I am getting the following errors when I compile:
**OUTPUT**
MPLINK 3.40, Linker
Copyright (c) 2003 Microchip Technology Inc.
Error - symbol 'axelWidth' has multiple definitions.
Errors : 1
BUILD FAILED: Sat Feb 07 11:04:01 2004
This is really annoying because it does not tell me where the other definitions are. In C++, and in this compiler, if I define the same thing twice explicitly, it tells me where the previous definition is. Here is a sample of my code:
Note: these are the only files that contain the definitions of these functions and varibles. There are NO duplicate names or any of that.
WHAT IS GOING ON!?!?!?!?!?!?!?!?!?
Clearly, including the file multiple times is prevented by the preprocessor #ifndef, #define, #endif statements, but it is acting like it just disregards those…
You defined axelWidth in userutilities.h and then included userutilities.h in userutilities.c… This means that axelWidth is defined as a float.
Now you redefine axelWidth as an external variable in userutilities.c meaning that some OTHER module has defined axelWidth. This is a double declaration and is only the tip of the iceberg… I see a bunch. i.e. you include bool.h multiple times…
Also, take a few minutes and see various threads about float variables and implicit initializations… You are going down a very dangerous road.
The problem is actually with the line “extern float axleWidth”. Since you’re including the header that has the declaration of “axleWidth” there is no need to re-declare it inside your function. ‘extern’ is only used when you have a global variable defined in another file.
From the names of your variables & the way you use them, it looks like those are values that will never change while your code is being executed, ie a constant. If so, there is no need to use a variable to store the values, use a #define instead:
and I have deleted the externs. Now the compiler has no trouble with “axelWidth”. Instead it says:
MPLINK 3.40, Linker
Copyright (c) 2003 Microchip Technology Inc.
Error - symbol 'newValue' has multiple definitions.
Errors : 1
BUILD FAILED: Sat Feb 07 12:05:03 2004
I wrote the function prototype in UserUtilities.h and the actual function definition in UserUtilities.c. There should be no conflicts here because prototypes ARE allowed.
Each time I fix a problem with one function or variable name in the set of files, it has a problem with the next one down the line.
Please consider that because bool.h has the necessary preprocessor statements, including it multiple times should not be a problem… right? Isn’t that the primary use of #ifndef, #define, and #endif structures in header files?
I also tried to delete the #include “userutilities.h” line from UserUtilities.c after making the above changes, but then it said that axelWidth and wheelRadius were not defined. Can I use extern with a variable that was #defined?
Well, the issue with floats is that this micro does not have a Floating Point Unit. So, while on your PC the FPU would quicky preform any math involving floats, that all has to be emulated in software on this micro. That is bad becuase that emulation is fairly complex and could potentially slow down your program considerably, especially if you use alot of floating point numbers.
The concerns about the implicit initializations, is basically that normally on microprocessors, the line
int i = 5;
may not automatically initalize i = 5. Though that is really a moot point in this case since IFI has a routine that does initalize the variables for us. (in ifi_startup.c for those who haven’t seen it.)
No, you can’t use extern with #define. #define isn’t actually a variable, what it means, is before the code is complied (in the pre-processor), the any time the first item after the #define is found, it is replaced with the second. So:
#define PI 3.1415926538
int C, R = 3;
C= 2PIR;
Becomes (after the pre-processor, but before the actuall compiler)
int C, R = 3;
C= 23.1415926538R;
So if you just put the
#define axelWidth .725
in one header file, that you include everywhere, you can use axelWidth with no other effort.
As an example, when using a microcontroller, using this:
#define PI (22 / 7)
is considerably faster than using 3.14159… and it gives a fairly decent approximation.
Also, to prevent re-inclusion of header files, people usually do something like this:
myheader.h #ifndef MYHEADER_H #define MYHEADER_H
… Entire header file …
#endif
/* ifndef MYHEADER_H */
This prevents weird recursion problems from having a header file included twice at the top of a C file.
It’s sloppy, and I don’t recommend doing this, because if you need to do this, you’re already down the dangerous road they’ve been speaking of and you ultimately need to fix that or you’ll just have a monstrous headache at competition when you’re rapidly changing code.
Constants that are #defined are usually all caps by convention.
Also, keep in mind that when using integers, order of operations isn’t the same as it is in your math class. Well, it is, but the order of operations will affect the result of the equation.
// Consider:
#define NUM 50
#define DEN 100
int foo = NUM / DEN * joy1_y
int bar = NUM * joy1_y / DEN
foo will ALWAYS be 0. Always. this is becuase NUM divided by DEN in integer math will be 0, and 0 multiplied by anything is zero. bar will contain what you think it should based on the equation.
Basically, stick to integer math, and multiply to the biggest number you can before starting to divide using integers to prevent always multoplying by zero.
This can be a dangerous aproach, as often the largest value is too large for the variable type that you are putting it in, but the final result would fit just fine. Just make sure that any intermediate values are not going to be too large before doing this.
second, the reason you are having problems is because mcc18 automatically casts any number from 0 to 255 as an unsigned char, which can screw up math. instead, what you’d want is this:
Ok, thanks for the info guys, but my problem still isn’t fixed. I still get the error about having multiple definitions, even though I don’t. I have included the preprocessor directives #ifndef, #define, #endif to prevent such nonsense from bothering me, but to no avail. I have written several functions that I NEED to make my robot work right, and it is extremely frustrating to have the compiler return errors that are unfounded.
:mad:
Please help!
My code is presented on the previous page, and I don’t want to re-post it because it is long… Please check it out and tell me why the function “newValue” keeps coming up as having “multiple definitions”!
notice that the error you are getting is a link error - this means that the multiple definitions are in different files - are you sure you didn’t accidentally name something (even a variable) newValue somewhere else?