Trouble with Unions in C program
I am working on a C program that uses a Union. The union definition is in FILE_A header file and looks like this...
// FILE_A.h****************************************************
xdata union
{
long position;
char bytes[4];
}CurrentPosition;
If I set the value of CurrentPosition.position in FILE_A.c and then call a function in FILE_B.c that uses the union, the data in the union is back to Zero. This is demonstrated below.
// FILE_A.c****************************************************
int main.c(void)
{
CurrentPosition.position = 12345;
SomeFunctionInFileB();
}
// FILE_B.c****************************************************
void SomeFunctionInFileB(void)
{
// After the following lines execute I see all zeros in the flash memory.
WriteByteToFlash(CurrentPosition.bytes[0];
WriteByteToFlash(CurrentPosition.bytes[1];
WriteByteToFlash(CurrentPosition.bytes[2];
WriteByteToFlash(CurrentPosition.bytes[3];
}
Now, If I pass a long to SomeFunctionInFileB(long temp) and then store it into CurrentPosition.bytes within that function, and finally call WriteBytesToFlash(CurrentPosition.bytes[n]... it works just fine.
It appears as though the CurrentPosition Union is not global. So I tried changing the union definition in the header file to include the extern keyword like this...
extern xdata union
{
long position;
char bytes[4];
}CurrentPosition;
and then putting this in the source (.c) file...
xdata union
{
long position;
char bytes[4];
}CurrentPosition;
but this cause开发者_开发百科s a compile error that says:
C:\SiLabs\Optec Programs\AgosRot\MotionControl.c:76: error 91: extern definition for 'CurrentPosition' mismatches with declaration.
C:\SiLabs\Optec Programs\AgosRot\/MotionControl.h:48: error 177: previously defined here
So what am I doing wrong? How do I make the union global?
Is FILE_A.h
really MotionControl.h
? If so I think the fix is to define a union type in the header:
typedef
union xdata
{
long position;
char bytes[4];
} xdata;
And declare a global variable of that type elsewhere in a header file (maybe the same one):
extern xdata CurrentPosition; // in a header file
Finally define the global variable in a C file exactly once. Maybe in file_a.c
:
xdata CurrentPosition;
Of course a better fix might be to pass the xdata
variable you want to write out to flash to SomeFunctionInFileB()
so you don't have to depend on a global variable, which are well known to be problematic when not very, very carefully used. And there seems to be no good reason to not pass the data as a parameter:
// in a header file
void SomeFunctionInFileB( xdata const* pPosition);
void SomeFunctionInFileB( xdata const* pPosition)
{
// After the following lines execute I see all zeros in the flash memory.
WriteByteToFlash(pPosition->bytes[0];
WriteByteToFlash(pPosition->bytes[1];
WriteByteToFlash(pPosition->bytes[2];
WriteByteToFlash(pPosition->bytes[3];
}
And call it like so:
int main.c(void)
{
CurrentPosition.position = 12345;
SomeFunctionInFileB( &CurrentPosition);
}
Ideally you need a typedef for the union and an extern declaration in FILE_A.h and the actual definition of the union in FILE_A.c.
-
// FILE_A.h
typedef union
{
long position;
char bytes[4];
} Position;
extern Position CurrentPosition; // declaration
-
// FILE_A.c
#include "FILE_A.h"
Position CurrentPosition; // definition
int main(void)
{
CurrentPosition.position = 12345;
SomeFunctionInFileB();
return 0;
}
-
// FILE_B.c
#include "FILE_A.h"
void SomeFunctionInFileB(void)
{
// now there will be valid data in the flash memory.
WriteByteToFlash(cp.bytes[0];
WriteByteToFlash(cp.bytes[1];
WriteByteToFlash(cp.bytes[2];
WriteByteToFlash(cp.bytes[3];
}
-
You haven't instantiated the union.
You need :
// FILE_A.c****************************************************
#include "File_a.h"
CurrentPosition cp;
int main(void)
{
cp.position = 12345;
SomeFunctionInFileB();
}
// FILE_B.c****************************************************
#include "File_a.h"
extern CurrentPosition cp;
void SomeFunctionInFileB(void)
{
// now there will be valid data in the flash memory.
WriteByteToFlash(cp.bytes[0];
WriteByteToFlash(cp.bytes[1];
WriteByteToFlash(cp.bytes[2];
WriteByteToFlash(cp.bytes[3];
}
If sizeof(long)
is not 4, then endianess comes into play...
consider
union{
long position
char bytes[sizeof long];
}
精彩评论