|
| 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!
| |
|
|