/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
bitshift
Fra : Troels Thomsen


Dato : 27-06-02 20:10

Hej

Hvilken type har: værdi << antal_bits
Og i hvilken grad afhænger det af processor/compiler ?

Jeg løb ind i noget eksisterende kode der virkede og så sådan ud:
(target: 8bit microcontroller, compiler: IAR fra '96)

char value = something
result = (unsigned long) (value<<24)

Til et andet projekt med samme target, men nyere compiler, saksede vi koden,
men det virkede ikke. Resultatet er altid nul fordi bitene bliver skuppet ud
af registeret (gætter jeg på), hvorefter det bliver castet til long. Der
skulle have stået sådan:

char value = something
result = ((unsigned long)value) << 24)

På en PC og msvc 6 er det ligegyldigt hvad man gør, antageligt fordi char'en
bliver lagt i et 32 bit register, og derefter skiftet op, således at bit'en
ikke forsvinder. Eller sker der et automatisk cast (promotion?) idet
compileren kan se at dette ikke kan være i en char? I så fald var det jo den
ældste compiler der var den smarteste...

mvh
Troels



 
 
Byrial Jensen (27-06-2002)
Kommentar
Fra : Byrial Jensen


Dato : 27-06-02 22:04

Troels Thomsen <troels.thom4sen@stofanet.dk> skrev:
> Hej
>
> Hvilken type har: værdi << antal_bits

I C har udtrykket samme type som typen af "værdi".

Bemærk at der er tale om udefineret adfærd hvis "antal_bits" er
negativ eller større end eller lig med bredden af "værdi".

> Og i hvilken grad afhænger det af processor/compiler ?

Det afhænger det ikke af.

> Jeg løb ind i noget eksisterende kode der virkede og så sådan ud:
> (target: 8bit microcontroller, compiler: IAR fra '96)
>
> char value = something
> result = (unsigned long) (value<<24)

Udtrykket (value<<24) har så typen char, og da typen char næppe har
mere end 24 bit på en 8-bit-microcontroller, er der tale om
udefineret adfærd. Dvs. at alt er tilladt.

> Til et andet projekt med samme target, men nyere compiler, saksede vi koden,
> men det virkede ikke. Resultatet er altid nul fordi bitene bliver skuppet ud
> af registeret (gætter jeg på), hvorefter det bliver castet til long.

Gættet er sikkert rigtigt, men alt muligt andet er som sagt også
tilladt.

> Der
> skulle have stået sådan:
>
> char value = something
> result = ((unsigned long)value) << 24)

Korrekt.

> På en PC og msvc 6 er det ligegyldigt hvad man gør, antageligt fordi char'en
> bliver lagt i et 32 bit register, og derefter skiftet op, således at bit'en
> ikke forsvinder. Eller sker der et automatisk cast (promotion?) idet
> compileren kan se at dette ikke kan være i en char?

Nej, der sker ikke en automatisk typekonvertering. Men med
udefineret adfærd kan alt tænkes. Hvis en bestemt oversætter har
lyst til automatiske konverteringer, er det også tilladt.

> I så fald var det jo den
> ældste compiler der var den smarteste...

En smart oversætter havde nægtet at oversætte det fejlbehæftede
kode.

Anders J. Munch (30-06-2002)
Kommentar
Fra : Anders J. Munch


Dato : 30-06-02 11:27

"Byrial Jensen" <bjensen@nospam.dk> skrev:
> > Hej
> >
> > Hvilken type har: værdi << antal_bits
>
> I C har udtrykket samme type som typen af "værdi".

C++: Når typen af 'vaerdi' er char så har udtrykket typen int[1],
ganske som Richard forklarede, på grund af integral promotions. Et
begreb jeg var overbevist om stammede fra C. Jeg er derfor tilbøjelig
til at tro at du tager fejl. Kan du pege på en implementation hvor
dette program udskriver '1'?

#include <stdio.h>
int main() { printf("%d", (int)sizeof((char)0 << 1)); }

> Troels Thomsen <troels.thom4sen@stofanet.dk> skrev:
> > Jeg løb ind i noget eksisterende kode der virkede og så sådan ud:
> > (target: 8bit microcontroller, compiler: IAR fra '96)

Jeg har prøvet at arbejde med en IAR compiler fra '96. Buggy as hell!
Men de nye versioner er gode.

- Anders

[1] Teoretisk kan der findes implementationer hvor den er unsigned int.




Byrial Jensen (30-06-2002)
Kommentar
Fra : Byrial Jensen


Dato : 30-06-02 14:46

Anders J. Munch <andersjm@inbound.dk> skrev:
> "Byrial Jensen" <bjensen@nospam.dk> skrev:
>> >
>> > Hvilken type har: værdi << antal_bits
>>
>> I C har udtrykket samme type som typen af "værdi".
>
> C++: Når typen af 'vaerdi' er char så har udtrykket typen int[1],
> ganske som Richard forklarede, på grund af integral promotions. Et
> begreb jeg var overbevist om stammede fra C. Jeg er derfor tilbøjelig
> til at tro at du tager fejl.

Jeg tog fejl. Du og Richard har ret. "værdi" udsættes for integral
promotion, og resultatet har samme type som værdi _efter integral
promotion_.

> Kan du pege på en implementation hvor
> dette program udskriver '1'?
>
> #include <stdio.h>
> int main() { printf("%d", (int)sizeof((char)0 << 1)); }

Ja, alle implementationer hvor char og int samme størrelse.
Og nej, jeg kender ingen konkrete implentationer hvor dette er
tilfældet.

Richard Flamsholt (29-06-2002)
Kommentar
Fra : Richard Flamsholt


Dato : 29-06-02 00:35

"Troels Thomsen" <troels.thom4sen@stofanet.dk> skrev:
>char value = something
>result = ((unsigned long)value) << 24)
>
>På en PC og msvc 6 er det ligegyldigt hvad man gør, antageligt fordi char'en
>bliver lagt i et 32 bit register, og derefter skiftet op, således at bit'en
>ikke forsvinder.

Når en char optræder som operand i et expression (som i fx c<<24) bliver
dens type automatisk konverteret til int. For PC+MSVC6 er en int 32 bit
og derfor virker det fint der.

>I så fald var det jo den ældste compiler der var den smarteste...

At koden virkede i den gamle compiler må skyldes enten

a) den gamle compiler definerede int som mindst 32 bit, mens
den nye compiler definerer (er indstillet til?) int som 16 bit
b) int er 16 bits, men den gamle compiler beregnede fejlagtigt
expressions i 32 bit mens den nye opfører sig korrekt
c) koden har i virkeligheden aldrig virket (et gammelt ubrugt levn)

--
Richard Flamsholt
richard@flamsholt.dk - www.richard.flamsholt.dk

Byrial Jensen (29-06-2002)
Kommentar
Fra : Byrial Jensen


Dato : 29-06-02 17:34

Richard Flamsholt <richard@flamsholt.dk> skrev:
> "Troels Thomsen" <troels.thom4sen@stofanet.dk> skrev:
>>char value = something
>>result = ((unsigned long)value) << 24)
>>
>>På en PC og msvc 6 er det ligegyldigt hvad man gør, antageligt fordi char'en
>>bliver lagt i et 32 bit register, og derefter skiftet op, således at bit'en
>>ikke forsvinder.
>
> Når en char optræder som operand i et expression (som i fx c<<24) bliver
> dens type automatisk konverteret til int. For PC+MSVC6 er en int 32 bit
> og derfor virker det fint der.

Undskyld jeg siger det, men det er noget vrøvl. Se min besvarelse
for en nærmere forklaring.

>>I så fald var det jo den ældste compiler der var den smarteste...
>
> At koden virkede i den gamle compiler må skyldes enten
>
> a) den gamle compiler definerede int som mindst 32 bit, mens
> den nye compiler definerer (er indstillet til?) int som 16 bit
> b) int er 16 bits, men den gamle compiler beregnede fejlagtigt
> expressions i 32 bit mens den nye opfører sig korrekt
> c) koden har i virkeligheden aldrig virket (et gammelt ubrugt levn)

Ad a) int er overhovedet ikke indblandet.
Ad b) int er overhovedet ikke indblandet.
Ad c) Her kommer du tættest på. Koden har aldrig været korrekt og
giver udefineret adfærd. Der er ingen grund til at overveje
hvilken konkret udefineret adfærd som en konkret oversætter
giver. Udefineret adfærd bør altid undgås!

Byrial Jensen (30-06-2002)
Kommentar
Fra : Byrial Jensen


Dato : 30-06-02 14:46

Byrial Jensen <bjensen@nospam.dk> skrev:
> Richard Flamsholt <richard@flamsholt.dk> skrev:
>>
>> Når en char optræder som operand i et expression (som i fx c<<24) bliver
>> dens type automatisk konverteret til int. For PC+MSVC6 er en int 32 bit
>> og derfor virker det fint der.
>
> Undskyld jeg siger det, men det er noget vrøvl.

UPS! Det er mig der vrøvler. Det er rigtigt at en char i de fleste
udtryk konverteres til int (eller unsigned int) før brugen, og at
det normalt er typen af den eller de konverterede operander som
afgør typen af resultatet.

Undskyld fejlen og beskyldningen for at vrøvle når det i
virkeligheden er mig som vrøvler!

>> At koden virkede i den gamle compiler må skyldes enten
>>
>> a) den gamle compiler definerede int som mindst 32 bit, mens
>> den nye compiler definerer (er indstillet til?) int som 16 bit
>> b) int er 16 bits, men den gamle compiler beregnede fejlagtigt
>> expressions i 32 bit mens den nye opfører sig korrekt
>> c) koden har i virkeligheden aldrig virket (et gammelt ubrugt levn)

Ja!

Søg
Reklame
Statistik
Spørgsmål : 177496
Tips : 31968
Nyheder : 719565
Indlæg : 6408491
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste