Gå til innhold

Hva er dette: *(unsigned long *)foo


Anbefalte innlegg

Sitter å leser en kode der jeg kom over dette:

	
void func(unsigned int *foo)
{
 double bar;
 ....
 ....
 ....
 *(unsigned long *)foo = (unsigned long)bar;
}

 

 

Sliter litt med å se greia til denne: *(unsigned long *)foo

og hvordan denne brukes utenfor funksjonen.

 

Noen som kan forklare?

Lenke til kommentar
Videoannonse
Annonse

Bare å begynne å løpe. Koden er ikke lovlig i det hele tatt og vil muligens kræsje hardt.

 

Vel,

*(unsigned long*)foo = bar;

 

betyr at foo castes til en peker til unsigned long, der innholdet av hva foo peker på blir satt til bar, som om det var en long, og ikke unsigned int. En annen måte å skrive det på er:

 

unsigned long *foo_long = (unsigned long*)foo; // OBSOBSOBSOBSOBS skummelt!
*foo_long = bar;

 

Koden vil sikkert kjøre fint på Windows, men vil ikke fungere som planlagt på Linux og OSX 64-bit er long er 64-bit og ikke 32-bit. (Hvorfor i all verden skriver folk kode som dette? Vi er i 2011, ikke 1999 ... <_<)

Endret av TheMaister
Lenke til kommentar

Pointer alias som å ha to pekere til samme plassering i minne?

 

Litt usikker på hvordan denne "foo" blir brukt videre, men jeg kan jeg anta at den er lagd slik for å kunne "hentes" fra andre metoder i programmet?

 

I C betyr pointer-alias at en blokk med minne blir pekt på av to eller flere pekere av ikke-kompatible typer. Det er skummelt og kan forårsake "morsomme" bugs.

 

unsigned int *foo; er en peker som peker på unsigned int. Når da pekeren blir castet til unsigned long*, en ikke kompatibel type, har vi pointer-alias. Hva som skjer da er ikke definert av C-standarden. Typisk går det bra, men har vært borti flere tilfeller der koden ikke virker i det hele tatt med kraftig optimisering.

Lenke til kommentar

(Hvorfor i all verden skriver folk kode som dette? Vi er i 2011, ikke 1999 ... <_<)

 

Men kanskje koden er skrevet i 1999 :)

 

Litt usikker på hvordan denne "foo" blir brukt videre, men jeg kan jeg anta at den er lagd slik for å kunne "hentes" fra andre metoder i programmet?

 

Peker til en lokal variabel som har gått ut av skop? Dårlig bissniss, bedre kjent som undefined behavior.

 

(Med unntak av i C++98/03 og C++0xb, hvor det er gyldig å referere til en lokal variabel returnert som reference-to-const, så lenge referansen eksisterer.)

 

I C og C++ heter det forresten funksjoner (og medlemsfunksjoner).

Lenke til kommentar

Datatypene er på en måte litt tåpelig definert. Grunnen er at alle er definert i forhold til hverandre.

 

char skal være minste adresserbare størrelse (mulig denne er definert til 1-byte)

short må være større enn char (vanligvis 2 byte)

int må være større eller lik short (vanligvis 4 byte)

long må være større eller lik int (på GCC under 64-bit kan denne være 64-bit, i Visual C++ og open Watcom er den alltid 32-bit)

long long må være større eller lik long (sannsynligvis 64-bit i både 32-bit og 64-bit kompilatorer)

 

float er 32-bit

double er 64-bit

long double er større eller lik double (standard oppførsel i GCC er at denne blir 128-bit, men dette kan variere. I VC++ er den synonymt med double)

 

Innen ting som skal brukes på tvers av programmer (som biblioteker etc) kan det være bedre å bruke int32_t og lignende (definert i C99) istedet ettersom C og C++ har en litt skrullete definisjon på datatypestørrelser.

Lenke til kommentar

long long må være større eller lik long (sannsynligvis 64-bit i både 32-bit og 64-bit kompilatorer)

 

Innen ting som skal brukes på tvers av programmer (som biblioteker etc) kan det være bedre å bruke int32_t og lignende (definert i C99) istedet ettersom C og C++ har en litt skrullete definisjon på datatypestørrelser.

 

long long må være minst 64-bit, og større eller like stor som long.

 

<stdint.h> er her for en grunn. Kode som ikke bruker int/uint*_t (eller tilsvarende) for størrelser som skal ha et visst antall bytes er broken. Har vært borti alt for mange tilfeller der kode har gått ut i fra at long er 32-bit. Dette ser jeg omtrent bare i Windows-kode (morsomt å porte slik kode), så kan være noe der at MSVC ikke fikk stdint.h før i 2010!

 

Grunnen til at C er veldig vag på dette med størrelser er for at man skal kunne implementere C effektivt på veldig merkelige systemer. Husk at CHAR_BIT ikke _må_ være 8. Noen maskiner som har 19-bit ord, osv, men det ser man nok ganske sjeldent i dag (heldigvis).

 

Hver gang man skriver short eller long bør man tenke seg godt om.

  • Liker 1
Lenke til kommentar

<stdint.h> er her for en grunn. Kode som ikke bruker int/uint*_t (eller tilsvarende) for størrelser som skal ha et visst antall bytes er broken. Har vært borti alt for mange tilfeller der kode har gått ut i fra at long er 32-bit. Dette ser jeg omtrent bare i Windows-kode (morsomt å porte slik kode), så kan være noe der at MSVC ikke fikk stdint.h før i 2010!

Win32 forventer i stor grad at long er 32-bit, og det er langt ifra det eneste. Dette er noe jeg har sett i ustrakt grad, og det er langt ifra bare Windows dette er et faktum på. Libvorbis er et eksempel.

Lenke til kommentar

Dette er nettopp hvorfor de fleste unngår rotete språk som C og C++ om de kan, de er rett og slett alt for svakt typet, noe som er farlig om du ikke vet hva du driver med.

 

C++ er ganske sterkt typet. Ikke Haskell-style, riktignok, men adskillig sterkere typet enn f.eks. Python, Ruby, JavaScript og andre utbredte språk. Grunnen til at de fleste har problemer med C og C++ er at de ikke lærer seg teknikker som gjør koden langt sikrere. Man må ta C og C++ som det de er, ikke som om de var Ada. (I C++0xb kan man for øvrig nærmest velge bort alle de "grisete detaljene".)

 

Man bør ikke skrive produksjonskode i noe språk uten at man vet hva man driver med. C og C++ velger å stole på programmereren, med den konsekvens at koden er raskere men potensielt mer lumsk.

 

Som nevnt av andre bør man uansett bruke <stddef.h> / <cstddef> hvis koden på noen som helst måte kan være avhengig av representasjonen til en type.

 

 

C/C++ er ikke problemløsning, det er problemskaping ;)

 

Jeg tror ikke du egentlig mener det. Jeg tror du skjønner at man bør bruke rett verktøy for rett oppgave, og at i enkelte tilfeller er det C eller C++ som er det verktøyet, mens det i andre tilfeller er andre verktøy som er bedre egnet. Det er for øvrig en grunn til at f.eks. Google og Facebook satser kraftig på C++, og at Microsoft gjenopptar C++-tråden sin i stor grad.

 

char skal være minste adresserbare størrelse (mulig denne er definert til 1-byte)

 

Jepp, sizeof(char) er garantert alltid, alltid lik 1 (byte), uten noen unntak noensinne. Som nevnt av noen andre har man derimot ingen garanti for at dette er åtte bit.

 

short må være større enn char (vanligvis 2 byte)

int må være større eller lik short (vanligvis 4 byte)

long må være større eller lik int (på GCC under 64-bit kan denne være 64-bit, i Visual C++ og open Watcom er den alltid 32-bit)

long long må være større eller lik long (sannsynligvis 64-bit i både 32-bit og 64-bit kompilatorer)

 

Dette er definert som minimumsspenn av verdier som hver type er nødt til å kunne representere. Se f.eks. side 22 i C99-spesifikasjonen.

 

long long må for øvrig være ekte større enn long.

 

Edit: Fant ikke noe som underbygger dette i standarden, så det kan være at kilden min tar feil. Men long long må minimum kunne representere +/- 2^63 − 1.

 

Innen ting som skal brukes på tvers av programmer (som biblioteker etc) kan det være bedre å bruke int32_t og lignende (definert i C99) istedet [...]

 

Definitivt! C++0xb har også disse typene.

 

 

Win32 forventer i stor grad at long er 32-bit, og det er langt ifra det eneste. Dette er noe jeg har sett i ustrakt grad, og det er langt ifra bare Windows dette er et faktum på. Libvorbis er et eksempel.

 

En grei antakelse. Og man vil jo aldri trenge mer enn maksimalt fire gigabyte minne... :)

Endret av Lstor
Lenke til kommentar

En grei antakelse. Og man vil jo aldri trenge mer enn maksimalt fire gigabyte minne... :)

 

Fra tid til annen snubler jeg over slik kode:

void *ptr = somedata;
unsigned int bar = (unsigned int)ptr;

 

.__.

Morro å finne slike bugs klokka 2 på natta, ja :D

Endret av TheMaister
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...