Hallo. Ich blättere gerade im RTOS Projekt. Welchen Grund gibt es für so einen Cast auf einen 32Bit System(Cortex): Konstante + (uint16_t)1; Oder soetwas: if(var1 == (unsigned short)0) Könnte man den Cast Operator auch weglassen? Danke Christian
Da die Befehle 32Bit Breit sind kann dort keine 32Bit Konstante im Befehl (als Immediate) stehen. Also muß die Konstate vorher in ein Register geladen werden und diese Register kann auch nicht direkt geladen werden sondern muß über einen Offset auf eine Speicherstelle geladen werden. Immediate Befehle konnten glaube ich eine 16Bit Konstante enthalten, womit dieser ganze Zirkus entfällt.
Christian schrieb: > Hallo. > > Ich blättere gerade im RTOS Projekt. Welchen Grund gibt es für so einen > Cast auf einen 32Bit System(Cortex): > > Konstante + (uint16_t)1; > > Oder soetwas: > if(var1 == (unsigned short)0) > > Könnte man den Cast Operator auch weglassen? Kommt drauf an... Wenn die Operanden nicht ganz zusammenpassen, wandelt sie der Compiler erstmal nach den Regeln des Standards in Integer um (Integer Promotion), wenn dem kein Riegel vorgeschoben wird. Da die Compiler auf 32-Bit Systemen int normalerweise als 32-Bit ansehen, wären hier u.U. entsprechende Umwandlung fällig, die dazu führen können, dass das Ergebnis nicht ganz das gewollte ist.
Das ist Quatsch. Die Kodierung der Konstanten im Maschinencode hat nichts mit dem Typ von Literalen und casts in C zu tun. Alle Integer Literale sind, falls nicht explizit anders angegeben, von Typ "int", welcher in ARM Compilern 32Bit (signed) ist. Christian schrieb: > Konstante + (uint16_t)1; Falls die Konstante vom Typ "int" ist (oder nicht "Konstante" sondern "Literal" gemeint war, und kein Typ angegeben ist, und somit vom Typ "int" ist) ist dieser cast absolut sinnlos. Die 1 wird danach wieder auf "int" promotet und die Rechnung auf "int" (32bit! ) durchgeführt. Christian schrieb: > if(var1 == (unsigned short)0) Hier kommt es auf den Typ von var1 an. Handelt es sich um einen builtin Integer Typen, ist der cast sinnlos. Nochmal: Der Compiler verwurstet alle Anweisungen und Literale mit Flussanalyse usw.. Wie sie im Code stehen hat keinen Einfluss auf die Kodierung im Maschinencode. Dafür sind Compiler Flags zur Optimierung zuständig (zB -Os vs -O3 im GCC).
Welcher Cortex? Zumindestens bei Cortex M kann man manche Muster, darunter auch (uint32_t) 1 immediate in ein Register laden. Fuer Cortex-M ist der cast oben m.e.a. ueberfluessig. Das ganze nennt sich "Flexible second operand".
Christian schrieb: > Könnte man den Cast Operator auch weglassen? Ja. Zumindest in den oben gezeigten zwei konkreten Fällen sind die komplett unsinnig.
Uwe Bonnes schrieb: > umindestens bei Cortex M kann man manche Muster, > darunter auch (uint32_t) 1 immediate in ein Register laden. Fuer > Cortex-M ist der cast oben m.e.a. ueberfluessig. Das ganze nennt sich > "Flexible second operand". Siehst Du hier etwa irgendwo Assembler code? Ich nicht. Das scheint ganz normales C zu sein, da gibts kein "immediate" und dergleichen, da gibts nur den C-Standard und darüberhinaus für grenzwertige Sachen die implemntation-defined sind noch das jeweilige ABI. Und weil nichts von den beiden Beispielen da oben je an einer "implementation defined" Grenze entlangschrammt reicht es allein den C-Standard zu betrachten.
Gemeint ist der Cortex-M. Die Casts tauchen immer wieder mal auf. Z.b. auch in der for-Schleife: BaseType_t x; for(x=(BaseType_t)0;x < (BaseType_t)Max_len;x++ ) BaseType ist abhängig von der entsprechenden Portierung, aber in diesem Falle ist es unsigned Long. Christian
Christian schrieb: > BaseType_t x; > for(x=(BaseType_t)0;x < (BaseType_t)Max_len;x++ ) > > BaseType ist abhängig von der entsprechenden Portierung, aber in diesem > Falle ist es unsigned Long. Der Autor dieses Codes zieht sich wohl die Hosen mit glühenden Beißzangen an. Heraus kommt dann grundlos überproportional unleserlicher Code.
Bernd K. schrieb: > Der Autor dieses Codes zieht sich wohl die Hosen mit glühenden > Beißzangen an. Heraus kommt dann grundlos überproportional unleserlicher > Code. Außerdem grundlos ineffizient, denn long ist (vermutlich) 64bit, während MaxLen vielleicht kleiner ist, und somit unnötig 64Bit gerechnet werden muss (Cortex M kann das nicht in Hardware) , falls der Compiler das nicht sowieso durchschaut und wegoptimiert. Insgesamt total sinnlos.Wenn schon aufwändig, dann bitte vom Typ von MaxLen abhängig:
1 | for (decltype (MaxLen) i = 0; i < MaxLen ; ++i) ... |
So wird die Arithmetik im größtnötigen Typ durchgeführt.
Programmierer schrieb: > Außerdem grundlos ineffizient, denn long ist (vermutlich) 64bit Nö, long ist 32 Bit bei Cortex M Compilern. Die vom OP genannten Casts sind IMO auf Prozessoren nötig, deren int nur 16 Bit breit sind. RTOS Projekte enthalten oft Code der auf verschiedenen Plattformen laufen muss.
Vermutlich stammt der Code aus FreeRTOS. Die werben mit größtmöglicher Portierbarkeit (8/16/32/64-Bit Maschinen) und Einhaltung aller MISRA-Regeln. Wahrscheinlich haben die casts damit etwas zu tun. uups... Jim war schneller
Jim Meba schrieb: > Nö, long ist 32 Bit bei Cortex M Compilern. Ah okay, hatte ih falsch in Erinnerung.. > Die vom OP genannten Casts sind IMO auf Prozessoren nötig, deren int nur > 16 Bit breit sind. RTOS Projekte enthalten oft Code der auf > verschiedenen Plattformen laufen muss. Klar, aber in dem Fall reicht es (und ist sowieso erforderlich! ) dem Schleifenzähler den richtigen Typ zu verpassen (der gleiche wie MaxLen). Die Casts sind dann unnötig, der Compiler macht bei Operatoren automatisch das richtige anhand des Typs der Variablen...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.