Vra

Ek het aan 'n aantal verskillende ingebedde stelsels gewerk.Hulle het almal gebruik typedefs (of #defines) vir tipes soos UINT32.

Dit is 'n goeie tegniek aangesien dit die grootte van die tipe na die programmeerder stuur en jou meer bewus maak van kanse vir oorloop ens.

Maar op sommige stelsels weet jy dat die samesteller en verwerker nie sal verander vir die lewe van die projek nie.

So wat moet jou besluit beïnvloed om projekspesifieke tipes te skep en af ​​te dwing?

Wysig ek dink ek het daarin geslaag om die kern van my vraag te verloor, en miskien is dit regtig twee.

Met ingebedde programmering benodig jy dalk tipes van spesifieke grootte vir koppelvlakke en ook om beperkte hulpbronne soos RAM te hanteer.Dit kan nie vermy word nie, maar jy kan kies om die basiese tipes van die samesteller te gebruik.

Vir al die ander is die tipes minder belangrik.
Jy moet versigtig wees om nie oorloop te veroorsaak nie en moet dalk oppas vir register- en stapelgebruik.Wat jou kan lei tot UINT16, UCHAR.Die gebruik van tipes soos UCHAR kan samesteller 'fluff' egter byvoeg.Omdat registers tipies groter is, kan sommige samestellers kode byvoeg om die resultaat in die tipe te dwing.

i++;
kan word
ADD REG,1
AND REG, 0xFF
wat onnodig is.

So ek dink my vraag moes gewees het:-

gegewe die beperkings van ingebedde sagteware, wat is die beste beleid om te stel vir 'n projek wat baie mense daaraan sal laat werk - nie almal sal van dieselfde vlak van ervaring hê nie.

Was dit nuttig?

Oplossing

Ek gebruik tipe abstraksie baie selde.Hier is my argumente, gesorteer in toenemende volgorde van subjektiwiteit:

  1. Plaaslike veranderlikes verskil van struktuurlede en skikkings in die sin dat jy wil hê hulle moet in 'n register pas.Op 'n 32b/64b teiken, 'n plaaslike int16_t kan kode stadiger maak in vergelyking met 'n plaaslike int, aangesien die samesteller bewerkings sal moet byvoeg by /force/ overflow volgens die semantiek van int16_t.Terwyl C99 'n definieer intfast_t typedef, AFAIK 'n gewone int sal net so goed in 'n register pas, en dit is sekerlik 'n korter naam.

  2. Organisasies wat van hierdie typedefs hou, eindig byna altyd met verskeie van hulle (INT32, int32_t, INT32_T, ad infinitum).Organisasies wat ingeboude tipes gebruik, is dus op 'n manier beter daaraan toe om net een stel name te hê.Ek wens mense gebruik die typedefs van stdint.h of windows.h of enigiets wat bestaan;en wanneer 'n teiken nie daardie .h-lêer het nie, hoe moeilik is dit om een ​​by te voeg?

  3. Die typedefs kan teoreties oordraagbaarheid aanhelp, maar ek, vir een, het nooit iets daaruit gekry nie.Is daar 'n nuttige stelsel wat u van 'n 32b-teiken na 'n 16b-teiken kan oordra?Is daar 'n 16b-stelsel wat nie triviaal is om na 'n 32b-teiken te koppel nie?Verder, as die meeste vars ints is, sal jy eintlik iets kry uit die 32 bisse op die nuwe teiken, maar as hulle int16_t, jy sal nie.En die plekke wat moeilik is om te port, vereis in elk geval handmatige inspeksie;voor jy 'n poort probeer, weet jy nie waar hulle is nie.Nou, as iemand dink dit is so maklik om dinge te porteer as jy typedefs oral het - wanneer die tyd by port kom, wat met min stelsels gebeur, skryf 'n script wat alle name in die kodebasis omskakel.Dit behoort volgens die "geen handmatige inspeksie vereis"-logika te werk, en dit stel die poging uit tot die tydstip waar dit werklik voordeel bied.

  4. Nou as draagbaarheid 'n teoretiese voordeel van die typedefs kan wees, leesbaarheid gaan seker in die drein.Kyk net na stdint.h: {int,uint}{max,fast,least}{8,16,32,64}_t.Baie soorte.'n Program het baie veranderlikes;is dit regtig so maklik om te verstaan ​​wat moet wees int_fast16_t en wat moet wees uint_least32_t?Hoeveel keer bekeer ons stilweg tussen hulle, wat hulle heeltemal nutteloos maak?(Ek hou veral van BOOL/Bool/eBool/boolean/bool/int-omskakelings.Elke program wat geskryf is deur 'n ordelike organisasie wat typedefs opdrag gee, is daarmee besaai).

  5. Natuurlik in C++ kan ons die tipe stelsel strenger maak deur nommers in sjabloonklas-instansies te verpak met oorlaaide operateurs en dinge.Dit beteken dat jy nou foutboodskappe van die vorm sal kry "klasnommer<int,minste,32> het geen operateur+ oorlading vir argument van tipe klas Nommer<unsigned long long,Fast,64>, candidates are..." I moet dit ook nie "leesbaarheid" noem nie.Jou kanse om hierdie omhulklasse korrek te implementeer is mikroskopies, en die meeste van die tyd sal jy wag vir die ontelbare sjabloon-instansies om saam te stel.

Ander wenke

Die C99-standaard het 'n aantal standaardgrootte heelgetaltipes.As jy 'n samesteller kan gebruik wat C99 ondersteun (gcc doen), sal jy dit vind in <stdint.h> en jy kan dit net in jou projekte gebruik.

Dit kan ook veral belangrik wees in ingebedde projekte om tipes as 'n soort "veiligheidsnet" te gebruik vir dinge soos eenheidsomskakelings.As jy C++ kan gebruik, verstaan ​​ek dat daar 'n paar "eenheid"-biblioteke daar buite is wat jou in fisiese eenhede laat werk wat deur die C++-tipe stelsel gedefinieer word (via sjablone) wat saamgestel word as bewerkings op die onderliggende skalaartipes.Byvoorbeeld, hierdie biblioteke sal jou nie toelaat om 'n distance_t aan a mass_t omdat die eenhede nie in lyn staan ​​nie;jy sal eintlik 'n samestellerfout kry.

Selfs as jy nie in C++ of 'n ander taal kan werk waarmee jy kode so kan skryf nie, kan jy ten minste die C-tipe stelsel gebruik om jou te help om foute soos dit met die oog op te vang.(Dit was eintlik die oorspronklike bedoeling van Simonyi se Hongaarse notasie.) Net omdat die samesteller nie op jou sal skree omdat jy 'n byvoeging van 'n meter_t aan a gram_t beteken nie dat jy nie sulke tipes moet gebruik nie.Kode-resensies sal dan baie meer produktief wees om eenheidsfoute te ontdek.

My mening is as jy afhanklik is van 'n minimum/maksimum/spesifieke grootte moenie neem net aan dat (sê) an unsigned int is 32 grepe - gebruik uint32_t in plaas daarvan (met die veronderstelling dat jou samesteller C99 ondersteun).

Ek hou daarvan om stdint.h-tipes te gebruik om stelsel-API's spesifiek te definieer omdat hulle uitdruklik sê hoe groot items is.Terug in die ou dae van Palm OS, is die stelsel-API's gedefinieer met behulp van 'n klomp wenslike tipes soos "Word" en "SWord" wat van baie klassieke Mac OS geërf is.Hulle het 'n skoonmaak gedoen om eerder Int16 te sê en dit het die API makliker gemaak vir nuwelinge om te verstaan, veral met die vreemde 16-bis-wyserkwessies op daardie stelsel.Toe hulle Palm OS Cobalt ontwerp het, het hulle daardie name weer verander om by stdint.h se name te pas, wat dit selfs meer duidelik gemaak het en die hoeveelheid tipedefs wat hulle moes bestuur, verminder het.

Ek glo dat MISRA-standaarde die gebruik van typedefs voorstel (vereis?).

Vanuit 'n persoonlike perspektief laat die gebruik van typedefs geen verwarring oor die grootte (in bisse / grepe) van sekere tipes nie.Ek het gesien hoe hoofontwikkelaars albei maniere probeer om te ontwikkel deur standaardtipes te gebruik, bv.int en gebruik pasgemaakte tipes bv.UINT32.

As die kode nie draagbaar is nie, is daar min werklike voordeel in die gebruik van typedefs, egter , as jy soos ek aan beide tipes sagteware (draagbare en vaste omgewing) werk, dan kan dit nuttig wees om 'n standaard te hou en die gesnyde tipes te gebruik.Ten minste soos jy sê, die programmeerder is dan baie bewus van hoeveel geheue hulle gebruik.Nog 'n faktor om te oorweeg, is hoe 'seker' jy is dat die kode nie na 'n ander omgewing oorgedra sal word nie?Ek het gesien hoe verwerker-spesifieke kode vertaal moet word as 'n hardeware-ingenieur het skielik 'n bord moes verander, dit is nie 'n lekker situasie om in te wees nie, maar as gevolg van die pasgemaakte tipe-definisies kon dit baie erger gewees het!

Konsekwentheid, gerief en leesbaarheid."UINT32" is baie meer leesbaar en skryfbaar as "unsigned long long", wat die ekwivalent vir sommige stelsels is.

Die samesteller en verwerker kan ook vir die lewe van 'n projek reggestel word, maar die kode van daardie projek kan dalk nuwe lewe in 'n ander projek vind.In hierdie geval is dit baie gerieflik om konsekwente datatipes te hê.

As jou ingebedde stelsels op een of ander manier a veiligheidskritiese stelsel (of soortgelyk), dit is sterk aangeraai (indien nie nodig nie) om typedefs oor gewone tipes te gebruik.

Soos TK. al voorheen gesê, MISRA-C het 'n (adviserende) reël om dit te doen:

Reël 6.3 (adviserende): tipedefs wat grootte en getekendheid aandui, moet in die plek van die basiese numeriese tipes gebruik word.

(uit MISRA-C 2004;dit is Reël #13 (adv) van MISRA-C 1998)


Dieselfde geld ook vir C++ in hierdie area;bv. JSF C++ koderingstandaarde:

AV-reël 209 'N Universaltypes -lêer sal geskep word om alle soorte Sta ndard vir ontwikkelaars te definieer.Die tipes sluit in:[uint16, int16, uint32_t ens.]

Met behulp van <stdint.h> maak jou kode meer draagbaar vir eenheidtoetsing op 'n rekenaar.

Dit kan jou nogal hard byt as jy toetse vir alles het maar dit breek steeds op jou teikenstelsel omdat 'n int is skielik net 16 bietjie lank.

Miskien is ek vreemd, maar ek gebruik ub, ui, ul, sb, si en sl vir my heelgetaltipes.Miskien lyk die "i" vir 16 bisse 'n bietjie verouderd, maar ek hou van die voorkoms van ui/si beter as uw/sw.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top