C99 - C99
C språkrevisjoner |
---|
C99 (tidligere kjent som C9X ) er et uformelt navn for ISO/IEC 9899: 1999 , en tidligere versjon av C -programmeringsspråkstandarden . Den utvider den forrige versjonen ( C90 ) med nye funksjoner for språket og standardbiblioteket , og hjelper implementeringer til å bedre bruke tilgjengelig datamaskinvare, for eksempel IEEE 754-1985 flytende aritmetikk og kompileringsteknologi. Den C11 versjon av programmeringsspråket C standard, publisert i 2011, erstatter C99.
Historie
Etter at ANSI produserte den offisielle standarden for programmeringsspråket C i 1989, som ble en internasjonal standard i 1990, forble C -språkspesifikasjonen relativt statisk en stund, mens C ++ fortsatte å utvikle seg, stort sett under sin egen standardiseringsinnsats. Normativ endring 1 opprettet en ny standard for C i 1995, men bare for å korrigere noen detaljer om standarden fra 1989 og for å legge til mer omfattende støtte for internasjonale tegnsett. Standarden ble ytterligere revidert på slutten av 1990 -tallet, noe som førte til publisering av ISO/IEC 9899: 1999 i 1999, som ble vedtatt som en ANSI -standard i mai 2000. Språket som ble definert av den versjonen av standarden, kalles vanligvis " C99 ". Den internasjonale C -standarden opprettholdes av arbeidsgruppen ISO/IEC JTC1/SC22 /WG14.
Design
C99 er for det meste bakoverkompatibel med C89, men den er strengere på noen måter.
Spesielt har en erklæring som mangler en typespesifikator ikke lenger int
implisitt antatt. C -standardkomiteen bestemte at det var mer verdt for kompilatorer å diagnostisere utilsiktet unnlatelse av typespesifikatoren enn å stille behandle eldre kode som var avhengig av implisitt int
. I praksis vil kompilatorer sannsynligvis vise en advarsel, deretter anta int
og fortsette å oversette programmet.
C99 introduserte flere nye funksjoner, hvorav mange allerede hadde blitt implementert som utvidelser i flere kompilatorer:
- innebygde funksjoner
- blandede erklæringer og kode: variabel erklæring er ikke lenger begrenset til filomfang eller starten på en sammensatt uttalelse (blokk), noe som letter statisk enkeltoppdragsskjema
- flere nye datatyper , inkludert
long long int
valgfrie utvidede heltallstyper, en eksplisitt boolsk datatype og encomplex
type for å representere komplekse tall - matriser med variabel lengde (selv om de senere ble henvist i C11 til en betinget funksjon som implementeringer ikke kreves for å støtte)
- fleksible array -medlemmer
- støtte for kommentarer på en linje som begynner med
//
, som i BCPL , C ++ og Java - nye bibliotekfunksjoner, som f.eks
snprintf
- nye overskrifter , slik som , , , og
<stdbool.h>
<complex.h>
<tgmath.h>
<inttypes.h>
- typegenerisk matematiske (makro) funksjoner, i
<tgmath.h>
, som velger en matematisk bibliotek funksjon er basert påfloat
,double
ellerlong double
argumenter, etc. - forbedret støtte for IEEE flytende punkt
- utpekt initializers (for eksempel initialisering av en struktur av feltnavn:
struct point p = { .x = 1, .y = 2 };
) - sammensatte liter (for eksempel, er det mulig å konstruere strukturer i funksjonskall:
function((struct x) {1, 2})
) - støtte for variatiske makroer (makroer med et variabelt antall argumenter)
-
restrict
kvalifisering tillater mer aggressiv kodeoptimalisering , og fjerner fordeler med kompileringstidstilgangstilgang som FORTRAN tidligere hadde i forhold til ANSI C - universelle tegnnavn, som lar brukervariabler inneholde andre tegn enn standard tegnsett
- søkeord
static
i matriseindekser i parameterdeklarasjoner
Deler av C99 -standarden er inkludert i den nåværende versjonen av C ++ - standarden, inkludert heltallstyper, overskrifter og bibliotekfunksjoner. Matriser med variabel lengde er ikke blant disse delene som er inkludert fordi C ++ s standardmalbibliotek allerede inneholder lignende funksjonalitet.
IEEE 754 flytende støtte
Et hovedtrekk ved C99 er numerisk støtte, og spesielt støtte for tilgang til funksjonene til IEEE 754-1985 (også kjent som IEC 60559) flytende punktmaskinvare som finnes i de aller fleste moderne prosessorer (definert i "Vedlegg F IEC 60559 flytende aritmetikk "). Plattformer uten IEEE 754 -maskinvare kan også implementere den i programvare.
På plattformer med IEEE 754 flytende punkt:
-
float
er definert som IEEE 754 enkel presisjon ,double
er definert som dobbel presisjon , oglong double
er definert som IEEE 754 utvidet presisjon (f.eks. Intel 80-biters dobbel utvidet presisjon på x86 eller x86-64 plattformer), eller en form for firepresisjon der dette er tilgjengelig; ellers er det dobbel presisjon. - De fire aritmetiske operasjonene og kvadratroten er korrekt avrundet som definert av IEEE 754.
FLT_EVAL_METHOD flyte dobbelt lang dobbel 0 flyte dobbelt lang dobbel 1 dobbelt dobbelt lang dobbel 2 lang dobbel lang dobbel lang dobbel - Uttrykksevaluering er definert som utført i en av tre veldefinerte metoder, som indikerer om flytende variabler først fremmes til et mer presist format i uttrykk:
FLT_EVAL_METHOD == 2
indikerer at alle interne mellomliggende beregninger utføres som standard med høy presisjon (lang dobbel) når tilgjengelig (f.eks. 80 bit dobbel utvidet ),FLT_EVAL_METHOD == 1
utfører alle interne mellomuttrykk i dobbel presisjon (med mindre en operand er lang dobbel), mensFLT_EVAL_METHOD == 0
spesifiserer at hver operasjon bare evalueres med presisjonen til den bredeste operanden til hver operatør. Den mellomliggende resultattypen for operander med en gitt presisjon er oppsummert i tabellen ved siden av.
FLT_EVAL_METHOD == 2
har en tendens til å begrense risikoen for avrundingsfeil som påvirker numerisk ustabile uttrykk (se IEEE 754 -designgrunnlaget ) og er den konstruerte standardmetoden for x87 -maskinvare, men gir uintuitiv oppførsel for den uforsiktige brukeren; FLT_EVAL_METHOD == 1
var standard evalueringsmetode som opprinnelig ble brukt i K&R C , som førte til at alle flyter ble doblet i uttrykk; og FLT_EVAL_METHOD == 0
er også ofte brukt og spesifiserer en streng "evaluer etter type" av operandene. (For gcc , FLT_EVAL_METHOD == 2
er standard på 32 bit x86, og FLT_EVAL_METHOD == 0
er standard på 64 bit x86-64, men FLT_EVAL_METHOD == 2
kan spesifiseres på x86-64 med opsjon -mfpmath = 387). Før C99, kompilatorer could rund mellomresultater inkonsistent, særlig når du bruker x87 flytende maskinvare, noe som fører til kompilatorspesifikk oppførsel; slike inkonsekvenser er ikke tillatt i kompilatorer som samsvarer med C99 (vedlegg F).
Eksempel
Følgende kommenterte eksempel C99 -kode for beregning av en fortsatt brøkfunksjon demonstrerer hovedfunksjonene:
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <fenv.h>
#include <tgmath.h>
#include <stdbool.h>
#include <assert.h>
double compute_fn(double z) // [1]
{
#pragma STDC FENV_ACCESS ON // [2]
assert(FLT_EVAL_METHOD == 2); // [3]
if (isnan(z)) // [4]
puts("z is not a number");
if (isinf(z))
puts("z is infinite");
long double r = 7.0 - 3.0/(z - 2.0 - 1.0/(z - 7.0 + 10.0/(z - 2.0 - 2.0/(z - 3.0)))); // [5, 6]
feclearexcept(FE_DIVBYZERO); // [7]
bool raised = fetestexcept(FE_OVERFLOW); // [8]
if (raised)
puts("Unanticipated overflow.");
return r;
}
int main(void)
{
#ifndef __STDC_IEC_559__
puts("Warning: __STDC_IEC_559__ not defined. IEEE 754 floating point not fully supported."); // [9]
#endif
#pragma STDC FENV_ACCESS ON
#ifdef TEST_NUMERIC_STABILITY_UP
fesetround(FE_UPWARD); // [10]
#elif TEST_NUMERIC_STABILITY_DOWN
fesetround(FE_DOWNWARD);
#endif
printf("%.7g\n", compute_fn(3.0));
printf("%.7g\n", compute_fn(NAN));
return 0;
}
Fotnoter:
- Kompiler med:
gcc -std=c99 -mfpmath=387 -o test_c99_fp -lm test_c99_fp.c
- Ettersom IEEE 754 -statusflaggene blir manipulert i denne funksjonen, er dette #pragma nødvendig for å unngå at kompilatoren feilordner slike tester ved optimalisering. (Pragma er vanligvis implementeringsdefinerte, men de som er prefiksert med
STDC
er definert i C-standarden.) - C99 definerer et begrenset antall uttrykksvurderingsmetoder: den nåværende kompileringsmodusen kan kontrolleres for å sikre at den oppfyller forutsetningene koden ble skrevet under.
- Spesielle verdier som NaN og positiv eller negativ uendelig kan testes og angis.
-
long double
er definert som IEEE 754 dobbel forlenget eller quad presisjon hvis tilgjengelig. Bruk av høyere presisjon enn nødvendig for mellomliggende beregninger kan minimere avrundingsfeil ( typefefendouble_t
kan brukes for kode som er bærbar under alleFLT_EVAL_METHOD
s). - Hovedfunksjonen som skal evalueres. Selv om det ser ut til at noen argumenter for denne fortsatte brøkdelen, f.eks. 3.0, ville føre til en divider-ved-null-feil, er funksjonen faktisk veldefinert til 3.0 og divisjon med 0 vil ganske enkelt returnere en +uendelig som da vil riktig føre til et endelig resultat: IEEE 754 er definert til ikke å fange slike unntak som standard og er utformet slik at de ofte kan ignoreres, som i dette tilfellet. (Hvis
FLT_EVAL_METHOD
er definert som 2, vil alle interne beregninger, inkludert konstanter, bli utført i lang dobbel presisjon; hvis detFLT_EVAL_METHOD
er definert som 0, er ytterligere forsiktighet nødvendig for å sikre dette, inkludert muligens flere kast og eksplisitt spesifikasjon av konstanter som lang dobbel.) - Siden det hevede divider-med-null-flagget ikke er en feil i dette tilfellet, kan det ganske enkelt avvises for å fjerne flagget for bruk av senere kode.
- I noen tilfeller kan andre unntak betraktes som en feil, for eksempel overløp (selv om det faktisk kan vises at dette ikke kan skje i dette tilfellet).
-
__STDC_IEC_559__
skal bare defineres hvis "Annex F IEC 60559 floating-point arithmetic" er fullt implementert av kompilatoren og C-biblioteket (brukere bør være klar over at denne makroen noen ganger er definert mens den ikke skal være det). - Standard avrundingsmodus er rund til nærmeste (med jevn avrundingsregel i halvveis tilfeller) for IEEE 754, men eksplisitt setter avrundingsmodus mot + og - uendelig (ved å definere
TEST_NUMERIC_STABILITY_UP
etc. i dette eksemplet, når feilsøking) kan brukes til diagnostisere numerisk ustabilitet. Denne metoden kan brukes selv om dencompute_fn()
er en del av et separat kompilert binært bibliotek. Men avhengig av funksjonen kan ikke numeriske ustabilitet alltid oppdages.
Versjonsdeteksjon
En standard makro __STDC_VERSION__
er definert med verdi for 199901L
å indikere at C99 -støtte er tilgjengelig. Som med __STDC__
makroen for C90, __STDC_VERSION__
kan den brukes til å skrive kode som vil kompilere annerledes for C90 og C99 -kompilatorer, som i dette eksemplet som sikrer at den inline
er tilgjengelig i begge tilfeller (ved å erstatte den med static
i C90 for å unngå linkerfeil).
#if __STDC_VERSION__ >= 199901L
/* "inline" is a keyword */
#else
# define inline static
#endif
Implementeringer
De fleste C -kompilatorer gir støtte for minst noen av funksjonene som ble introdusert i C99.
Historisk sett har Microsoft vært treg med å implementere nye C -funksjoner i sine Visual C ++ - verktøy, i stedet fokusert hovedsakelig på å støtte utviklingen i C ++ - standardene. Men med introduksjonen av Visual C ++ 2013 implementerte Microsoft et begrenset delsett av C99, som ble utvidet i Visual C ++ 2015.
Kompilator | Støttenivå | C99 -kompatibilitetsdetaljer |
---|---|---|
Acorn C/C ++ | Delvis | Den offisielle dokumentasjonen sier at "de fleste" kompilatorfunksjonene støttes, sammen med "noen" av bibliotekfunksjonene. |
AMD x86 Open64 Compiler Suite | For det meste | Har C99 -støtte som er lik GCC. |
cc65 | Delvis | Full støtte for C89 og C99 er ikke implementert, delvis på grunn av plattformbegrensninger ( MOS Technology 6502 ). Det er ingen planlagt støtte for noen C99-typer som _Complex og 64-bits heltall (langt langt). |
Ch | Delvis | Støtter store C99 -funksjoner. |
Clang | For det meste | Støtter alle funksjoner unntatt C99 flytende punkt-pragmer. |
CompCert | For det meste | En sertifisert kompilator, formelt vist seg å være korrekt. Støtter alle funksjoner bortsett fra komplekse C99 -numre og VLA, og mindre restriksjoner på switch -setninger (ingen Duff -enhet ). |
cparser | Full | Støtter C99 -funksjoner. |
C ++ Builder | Bare i 64-biters modus, siden sistnevnte er CLang-gaffel |
|
Digital Mars C/C ++ kompilator | Delvis | Mangler støtte for noen funksjoner, for eksempel < tgmath.h > og _Pragma. |
GCC | For det meste | Fra juli 2021 mangler standard pragmer og IEEE 754/IEC 60559 flytende punktstøtte i hovedlinjen GCC. I tillegg må noen funksjoner (for eksempel utvidede heltallstyper og nye bibliotekfunksjoner) leveres av C -standardbiblioteket og er utenfor rekkevidde for GCC. GCCs 4.6 og 4.7 utgivelser gir også det samme nivået av samsvar. Delvis IEEE 754 -støtte, selv når maskinvaren er kompatibel: Noen kompilatoralternativer kan være nødvendige for å unngå feiloptimaliseringer (f.eks. -std=c99 Og -fsignaling-nans ), men full støtte for riktede avrundingsmoduser mangler selv når den -frounding-math brukes.
|
Green Hills -programvare | Full | |
IBM C for AIX, V6 og XL C/C ++ V11.1 for AIX | Full | |
IBM Rasjonelt logiskop | Full | Fram til Logiscope 6.3 ble bare grunnleggende konstruksjoner av C99 støttet. C99 støttes offisielt i Logiscope 6.4 og nyere versjoner. |
Portland Group PGI C/C ++ | Full | |
IAR Systems Embedded Workbench |
For det meste | Støtter ikke UCN (universelle tegnnavn). Kompilator for innebygde mål, for eksempel ARM, Coldfire, MSP430, AVR, AVR32, 8051, ... Ingen x86 -mål. |
Intel C ++ - kompilator | For det meste |
|
Microsoft Visual C ++ | Delvis | Visual C ++ 2012 og tidligere støttet ikke C99. Visual C ++ 2013 implementerer et begrenset delsett av C99 som kreves for å kompilere populære open source-prosjekter. Visual C ++ 2015 implementerer standardbiblioteket C99, med unntak av alle bibliotekfunksjoner som er avhengige av kompilatorfunksjoner som ennå ikke støttes av kompilatoren (for eksempel < tgmath.h > er ikke implementert). Visual C ++ 2019 (16.6) legger til opt-in-støtte for en C99-konform prosessor. |
Åpne Watcom | Delvis | Implementerer de mest brukte delene av standarden. Imidlertid aktiveres de bare gjennom den udokumenterte kommandolinjebryteren "-za99". Tre C99-funksjoner har blitt samlet som C90-utvidelser siden pre-v1.0: C ++-stilkommentarer (//), fleksible array-medlemmer, etterfølgende komma tillatt i enum-erklæring. |
Pelles C | Full | Støtter alle C99 -funksjoner. |
Bærbar C -kompilator | Delvis | Jobber for å bli C99-kompatibel. |
Sun Studio | Full | |
The Amsterdam Compiler Kit | Nei | En C99 -frontend er nå under etterforskning. |
Tiny C -kompilator | Delvis | Støtter ikke komplekse tall. Variable Length Arrays støttes, men ikke som argumenter i funksjoner. Utviklerne uttaler at "TCC er på vei mot full ISOC99 -samsvar". |
vbcc | Delvis |
Fremtidig arbeid
Siden ratifiseringen av C -standarden fra 1999 utarbeidet standardgruppen tekniske rapporter som spesifiserte forbedret støtte for innebygd behandling, ytterligere tegndatatyper ( Unicode -støtte) og bibliotekfunksjoner med forbedret grensekontroll . Det arbeides videre med tekniske rapporter som omhandler desimal flyttall , flere matematiske spesielle funksjoner , og ytterligere dynamisk minne allokering funksjoner. Standardkomiteene C og C ++ har samarbeidet om spesifikasjoner for gjenget programmering.
Den neste revisjonen av C -standarden, C11 , ble ratifisert i 2011. C -standardkomiteen vedtok retningslinjer som begrenset adopsjonen av nye funksjoner som ikke har blitt testet av eksisterende implementeringer. Mye innsats ble gjort for å utvikle en minnemodell for å klargjøre sekvenspunkter og for å støtte gjenget programmering.
Se også
- C ++ 20 , C ++ 17 , C ++ 14 , C ++ 11 , C ++ 03 , C ++ 98 , versjoner av C ++ programmeringsspråkstandarden
- Kompatibilitet med C og C ++
- C ++ Teknisk rapport 1
- Flytpunkt , for videre diskusjon om bruk av IEEE 754 maskinvare
Referanser
Videre lesning
- Cheng, Harry (1. mars 2002). "C99 og numerisk databehandling" . Dr. Dobb's Journal .
- Seebach, Peter (24. mars 2004). "Åpen kildekode -utvikling ved hjelp av C99" . developerWorks . IBM .
- "Endelig versjon av C99 -standarden med korrigeringer TC1, TC2 og TC3 inkludert, formatert som et utkast" (PDF) . (3,61 MB)
- Begrunnelse for internasjonal standard-programmeringsspråk-C revisjon 5.10 , april 2003, begrunnelse for C99