2010-05-04 3 views
3

Je travaille sur un programme C qui utilise une Union. La définition de l'union est dans le fichier d'en-tête FILE_A et ressemble à ceci ...Problème avec les syndicats dans le programme C

// FILE_A.h**************************************************** 
xdata union 
{ 
long position; 
char bytes[4]; 
}CurrentPosition; 

Si je mets la valeur de CurrentPosition.position dans FILE_A.c puis appeler une fonction dans FILE_B.c qui utilise le syndicat, la les données dans l'union sont de retour à zéro. Ceci est démontré ci-dessous.

// 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]; 
} 

Si je passe un temps à SomeFunctionInFileB (longue temp) puis le stocker dans CurrentPosition.bytes dans cette fonction, et enfin appeler WriteBytesToFlash (CurrentPosition.bytes [n] ... il fonctionne très bien .

Il semble que l'Union currentPosition est pas globale. J'ai essayé de changer la définition du syndicat dans le fichier d'en-tête pour inclure le mot-clé extern comme ça ...

extern xdata union 
{ 
long position; 
char bytes[4]; 
}CurrentPosition; 

puis mettre cela dans la fichier source (.c) ...

xdata union 
{ 
    long position; 
    char bytes[4]; 
}CurrentPosition; 

mais cela provoque une erreur de compilation qui dit:

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

Alors qu'est-ce que je fais mal? Comment rendre le syndicat global?

+0

Je pense - mais je ne suis pas sûr - que les travaux du syndicat façon est que si vous accédez à t Les données à travers une de ses variables puis les autres sont effectivement invalidées. En d'autres termes, je ne crois pas que vous pouvez définir le long et ensuite utiliser les octets pour accéder à cette mémoire. Vous devriez y accéder à long terme. Je ne suis pas positif à ce sujet si - d'où le commentaire. Je suis curieux de voir ce que disent les plus expérimentés des syndicats. –

+1

@Daniel - incorrect - exactement le contraire est vrai, c'était l'objectif initial d'une union pour avoir accès aux octets de long ou un int ou un flotteur - dangereux et dépendants de la machine qu'ils sont ..... – KevinDTimm

+4

Je jure que je lire le titre comme «Trouble with Unicorns in C program». Je passe trop de temps sur Meta. –

Répondre

7

Est-FILE_A.h vraiment MotionControl.h? Si donc je pense que la solution est de définir un type d'union dans l'en-tête:

typedef 
union xdata 
{ 
    long position; 
    char bytes[4]; 
} xdata; 

Et déclarer une variable globale de ce type ailleurs dans un fichier d'en-tête (peut-être le même):

extern xdata CurrentPosition; // in a header file 

Enfin définir la variable globale dans un fichier C exactement une fois.Peut-être dans file_a.c:

xdata CurrentPosition; 

Bien sûr, une meilleure solution pourrait être de passer la variable xdata vous voulez écrire à clignoter pour SomeFunctionInFileB() de sorte que vous ne devez pas dépendre d'une variable globale, qui sont bien connus être problématique quand pas très, très soigneusement utilisé. Et il semble y avoir aucune bonne raison de ne pas transmettre les données en tant que paramètre:

// 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]; 
} 

et l'appeler comme ceci:

int main.c(void) 
{ 
    CurrentPosition.position = 12345; 
    SomeFunctionInFileB(&CurrentPosition); 
} 
+0

Dans la définition de l'union, pourquoi mettez-vous 'xdata' à deux endroits? Cela ne fait-il pas le nom de l'union 'xdata'? – PICyourBrain

+0

Mon intention était d'utiliser le mot-clé xdata pour dire au compilateur de mettre la variable dans la mémoire externe plus lente. Ce programme est pour un périphérique intégré. – PICyourBrain

+0

Oh - Je pensais que «xdata» était censé être le nom du type d'union. Si 'xdata' est un mot-clé/attribut pour que le compilateur place des données à un endroit spécifique, ajustez-le en conséquence (donnez un nom approprié au type d'union et placez l'attribut' xdata' sur la variable). –

2

Idéalement, vous avez besoin d'un typedef pour le syndicat et une déclaration extern dans FILE_A.h et la définition réelle du syndicat 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]; 
} 

-

1

Vous n'êtes pas instancié le syndicat.
Vous avez besoin:

// 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]; 
} 
+0

[whining rant] bummer - Je vois que je dois d'abord poster mes réponses incomplètes, puis les étoffer ... [/ whiny rant] – KevinDTimm

0

Si sizeof(long) n'est pas 4, puis endianess entre en jeu .. .

considèrent

union{ 
    long position 
    char bytes[sizeof long]; 
}