Korrekt enligt C-standard?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Korrekt enligt C-standard?

Inlägg av arte »

Hej,

Jag undrar ifall denna kod snutten bryter mod C-standarden på något sätt:

Kod: Markera allt

static short FSHORT(short x)
{
  return (((unsigned char *) &x)[1]<< 8) +
          ((unsigned char *) &x)[0];
}

void main()
{
	printf("Val %d \n",FSHORT(1));
}
Den fungar på en arch men inte en annan. Ifall x hamnar på stacken så fungerar det men ifall det hamnar i ett register så blir det så klart knas.
Inga vidare bra kod men nyfiken på vad C standarden säger.

Någon som vet?
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Korrekt enligt C-standard?

Inlägg av johano »

Koden förutsätter att storleken på unsigned char är mindre än storleken på short vilket inte nödvändigtvis är fallet...det finns system där sizeof(char)==sizeof(short)

/johan
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Korrekt enligt C-standard?

Inlägg av blueint »

Helt otestat:

Kod: Markera allt

static short FSHORT(short x)
{
  return (
(* (((unsigned char *) &x)+1) )<< 8) |
(* (((unsigned char *) &x)+0) )<<0)  );
}
Kanske fungerar bättre? eller någon variation därav.

Ta dock en rejäl kik på vad sizeof(short) och sizeof(char) ger.
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Re: Korrekt enligt C-standard?

Inlägg av arte »

Fast det stora problemet är väl att ta addressen av ett argument.
Altså:

Kod: Markera allt

void func(int r0)
{
    int *ptr = &r0;

    return *ptr;
}
I koden ovan kommer ptr inte kunna peka till något vettigt?
Ifall variablen r0 är sparad i ett register så blir det inge bra.

Jag söker inte efter en lösning utan bara nyfiken på hur C fungerar.
(lösningen på problemet är att spara r0 i en lokal variabel innan man referar till det)
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Korrekt enligt C-standard?

Inlägg av blueint »

Testat att det fungerar:

Kod: Markera allt

static short FSHORT1(short x)
{
return
      (*(((unsigned char *)&x)+1)<<8) |
      (*(((unsigned char *)&x)+0)<<0);
}
Kombinera gärna med denna huvudfunktion:

Kod: Markera allt

int main()
{
  printf("short=%u  char=%u\n",sizeof(short), sizeof(char) );
  printf("Val 0x%04X\n",FSHORT1(0x1234));

return 0;
}
Anledningen till att jag blev lite fundersam på din funktion var att den innehöll en referens till "short x" som en array när det är en address som använts.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Korrekt enligt C-standard?

Inlägg av bearing »

Huruvida argument sparas i register eller RAM har med "calling conventions" på den aktuella architekturen att göra.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Korrekt enligt C-standard?

Inlägg av blueint »

Vilka arkitekturer rör det sig om?
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Korrekt enligt C-standard?

Inlägg av Icecap »

Det kan fungera OK men det beror på endian för systemet. Det bör fungera för little endian men för big endian blir det fel.

Sedan kan det komma problem med register osv. beroende på målsystem, t.ex. PIC har ju ingen stack som sådan att överföra värden i varför register kan bli inblandat.

Men jag skulle definitivt kolla på endian innan jag gick vidare.
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Korrekt enligt C-standard?

Inlägg av johano »

Det är naturligtvis helt legalt i C att ta adressen av en funktionsparameter, det är kompilatorns jobb att se till att den hamnar rätt om den nu skickades via ett register.

Om detta inte funkar i ditt fall så är det en bugg i kompilatorn.

Vad är det för plattform/kompilator?

/johan
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Korrekt enligt C-standard?

Inlägg av sodjan »

Detta kanske kan flyttas till "Programmering"?
Jag ser ingen referens till något specifik plattform eller hårdvara.

> Den fungar på en arch men inte en annan.

Vad betyder "fungerar"? Vad förväntas och vad är skillnaden mellan olika "arch"?

> Ifall x hamnar på stacken så fungerar det men ifall det hamnar i ett register så blir det så klart knas.

Vad betyder "knas" mer specifikt? Crasch? Skräpvärden?

Själv får jag bara samma värde ut från fprint som in till FSHORT().
Om det är förväntat så fungerar det oavsett hur jag skruvar på
optimeringen.

Hela FSHORT() kör mot register och blir 6 maskininstruktiner (inkl RETURN).
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Re: Korrekt enligt C-standard?

Inlägg av mri »

Skall du göra det där korrekt måste du gå via en union.

Jag har själv spenderat många timmar på att leta efter en bugg som kom utav ditt förslag att typkonvertera genom en pekare. Den buggiga koden var skriven för visual c kompilatorn var allt funkade okay. Med gcc och ganska aggressiv optimering blev det fel i vissa fall eftersom kompilatorn ändrade ordningsföljden.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Korrekt enligt C-standard?

Inlägg av sodjan »

Vad är det korrekta "svaret"?
Med FSHORT(1234) skriver fprint() ut "Val 1234".
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Re: Korrekt enligt C-standard?

Inlägg av mri »

arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Re: Korrekt enligt C-standard?

Inlägg av arte »

johano skrev:Det är naturligtvis helt legalt i C att ta adressen av en funktionsparameter, det är kompilatorns jobb att se till att den hamnar rätt om den nu skickades via ett register.

Om detta inte funkar i ditt fall så är det en bugg i kompilatorn.

Vad är det för plattform/kompilator?
/johan
Lite detta jag fiskade efter!

Det är GCC och platformen är ZPU (en OpenSource processor).
Kan mycket väl vara buggar i den kompilatorn.

Så det är fullt legalt att göra så?
blueint skrev:Vilka arkitekturer rör det sig om?
Fungerar på ARMv7, x86 fungerar inte på ZPU.
Men som johan säger så skall det fungera på alla arch.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Korrekt enligt C-standard?

Inlägg av sodjan »

Jag har fortfarande inte förstått vad "fungerar" betyder här.
Exakt vilket resultat förväntas? Eller betyder "fungerar"
bara att det går att kompilera?
Skriv svar