Sida 1 av 1

undran om en Union

Postat: 28 augusti 2005, 00:16:06
av dangraf
Jag skriver kod för att lagra data i ett eeprom minne.

Ibland måste jag spara och läsa en "header" som kan består av t.ex

float fvärde1; //4byte
float fvärde2; //4bute
long tid; //4byte
int adress; //2 byte

Eftersom jag får skicka/ta emot värdena i form av bytes till mitt eeprom så hade det varit göttit ifall jag kunnat göra en "union" eller liknande.

jag hade viljat ha det ung som

Kod: Markera allt


union
{
  struct{
     float  fvärde1;    //4byte
     float  fvärde2;    //4bute
     long  tid;           //4byte
     int    adress;      //2 byte
  }v;
  unsigned char c[14];

}u_test;
MEN!! Om man skriver som mitt exempel ovan, så måste jag skriva t.ex:

utest.v.fvärde1

för att komma åt mitt float värde1.

Går det att deklarera min "union" så att jag slipper "v"et och på så sätt få det snyggare?

Postat: 28 augusti 2005, 00:52:12
av cyr
Ja, det ska gå (kanske beroende på din kompilator).

GCC stöder det iaf:

http://www.redhat.com/docs/manuals/ente ... ields.html

" For compatibility with other compilers, GCC allows you to define a structure or union that contains, as fields, structures and unions without names "

Alltså, du kan ha en struct utan namn i din union. Och delarna i structen kommer du åt som om de låg direkt i din union.

Postat: 28 augusti 2005, 15:26:07
av dangraf
Det var så enkelt alltså :-) tackar!!

Postat: 28 augusti 2005, 20:43:41
av Icecap
Man kan även göra såhär:

Kod: Markera allt

  struct{
     float  fvärde1;    //4byte
     float  fvärde2;    //4bute
     long  tid;           //4byte
     int    adress;      //2 byte
  }v;
unsigned char Counter;
for(Counter = 0;Counter < sizeof(v);Counter++)
  {
  Save2EEPROM(*(char*)&v+Counter);
  }
Det betyder:
Värdet som den om-castade (address_till_v + Counter) pekar på hämtas och "Save2EEPROM" kallas med det värde. Den är lite tricky men fullt legal.

Postat: 2 september 2005, 12:36:10
av mindless
Tänkte bara tillägga att en struct kan vara större än summan av dess fält, pga padding. Speciellt om man har korta sådana i mitten av en struct. Därför kan det skrivas onödig data till EEPROMet i bästa fall, eller att man missar att skriva hela structen i värsta fall.

http://www.lysator.liu.se/c/c-faq/c-9.html#9-10

Och även:
Har inte precedence reglerna i huvudet men tror det ska vara
Save2EEPROM(*((char*)&v+Counter));

Postat: 2 september 2005, 20:37:23
av Icecap
Anledningen till att jag skrev 'sizeof(struct)' är just att man inte ska räkna ut storleken själv, det tar kompilern hand om.

Sen har deklarationen av Save2EEPROM ju en roll också men det blir väldigt specifik då och det beror ju på hårdvara osv.

Jag använder denna deklaration:

Kod: Markera allt

void Write_EE_Buffer(unsigned int Address, unsigned char * XBuffer, unsigned int Length)
  {
  unsigned char Part;
  while(Length)
    {
    Part = 0x10 - (Address & 0x0F);
    if(Length < Part) Part = Length;
    Length -= Part;
    Write_EE_Enable();             /* Allow it to be programmed */
    EE_NCS = 0;                    /* Activate *CS */
    SPI_Write_Data(EE_WRITE); /* Command a WRITE */
    SPI_Write_Word(Address);  /* Send Address */
    while(Part)
      { /* While within one bank send data */
      SPI_Write_Data(*XBuffer);
      XBuffer++;  /* Point on next byte */
      Part--;    /* Count down */
      Address++; /* Count up address */
      }
    EE_NCS = 1;
    while(Read_EE_Status() & EE_S_WIP); /* Wait for bank to be finished */
    }
  }

När jag kallar den rutin anroper jag den via en enklare rutin:
void Save_Configuration(void)
  {
  Write_EE_Buffer(0,(byte*)&Config,sizeof(Config));
  }
så jag känner mig ganska säker på att jag har refererat rätt, det är fungerande kod, testat under en del år.