Själv tycker jag generellt riktigt illa om "typdeffar". Det gör att det blir betydligt svårare att hitta buggar eftersom man inte vet vad som finns bakom "AdcSteps". Rymmer variabeln 8, 16 eller 32 bitar? Är den signed eller unsigned? Man får inte heller någon extra typsäkerhet (tyvärr!) eftersom kompilatorn konverterar heltalsvariabler bakom ryggen på en.SvenW skrev:*snip*
Typdeffar är bra om typen används på många ställen, och i anslunting till typdeffen kan man kommentera närmare hur man tänker, så man inte behöver lägga samma information i kommentarer på många ställen.
ex:
typedef int16_t AdcSteps; // One ADCstep is 1 mV
...
const AdcSteps v_ref = 4096;
...
Mycket bättre då att använda den faktiska typen direkt.
På rak arm kan jag komma på ett enda tillfälle där typedef kan vara OK:
1) För att förtydliga variabeltypen:
Kod: Markera allt
#include <stdlib.h>
#include <stdio.h>
typedef int int16;
#define COMPILE_TIME_ASSERT(pred) \
switch (0) { case 0: case (pred): default: ; }
int main(void)
{
/*
* Make sure the data types are of the correct size.
* These checks will complain like this if the predicate is
* false:
* error: duplicate case value
*/
COMPILE_TIME_ASSERT(sizeof(int16) == 2);
printf("Hello, world!\n");
return EXIT_SUCCESS;
}
Ett tillfälle som inte är bra är om man inte är riktigt säker på vilken datatyp man kommer att vilja ha i slutändan, och vill kunna ändra "lätt", genom att bara ändra sin typedef. Detta är som gjort för att skapa svårupptäckta buggar i programmet - man har ju skrivit koden med utgångspunkt att man har en variabel av en viss typ. Ändrar man sen typ så ber man om buggar som dyker upp förr eller senare.
... och om du försöker lagra 0.1 i 8.8 fixed format så blir det 0.1015625. Du får inte sämre precision med flyttal än med fixed point av samma storlek.Findecanor skrev:Flyttal skrivs i decimal, men lagras i binärt, dvs. basen 2. Visst får du precision, men det är inte alltid som det du skrivit är exakt det som lagras i variabeln. T.ex. om du skriver "0.1" så får du egentligen "0.10001".
Dock, om man gör som TS föreslår och enbart använder flyttal för att beräkna konstanter som går att beräkna vid kompileringstillfället, och castar dem till heltal när de är "klara", så sköter kompilatorn om all flyttalsmatte och det blir bara heltalsmatte kvar för processorn. Jag tycker att det verkar som en bra strategi!Findecanor skrev:Jag tror inte heller att det är vanligt att microcontrollers har något flyttalsenhet, vilket gör att de måste emuleras, vilket inte har någon bra prestanda och därför bör undvikas i tidskritisk kod.
Vill man sedan fortsätta räkna med högre precision än heltal under körning så kan man ju multiplicera konstanterna med en potens av två och använda fixed point.
TS:
gcc verkar ha stöd för parametern -mno-soft-float för åtminstone någon arkitektur. Vet inte om det funkar för dig.
Konstanter som anges med decimalkomma och utan efterföljande f är för övrigt inte av typen float ("1.0f"), utan av typen double ("1.0"). Vilket väl bara är bra så länge kompilatorn tar hand om matten.