C99 - C99

Kryt standardního dokumentu C99

C99 (dříve známý jako C9X ) je neformální název pro ISO/IEC 9899: 1999 , předchozí verzi standardu programovacího jazyka C. Rozšiřuje předchozí verzi ( C90 ) o nové funkce pro jazyk a standardní knihovnu a pomáhá implementacím lépe využívat dostupný počítačový hardware, jako je aritmetika s plovoucí desetinnou čárkou IEEE 754-1985 a technologie kompilátoru. Verze C11 standardu programovacího jazyka C, publikovaná v roce 2011, nahrazuje C99.

Dějiny

Poté, co ANSI v roce 1989 vytvořilo oficiální standard pro programovací jazyk C, který se v roce 1990 stal mezinárodním standardem, zůstala specifikace jazyka C po určitou dobu relativně statická, zatímco C ++ se nadále vyvíjel, převážně během vlastního úsilí o standardizaci. Normativní dodatek 1 vytvořil nový standard pro C v roce 1995, ale pouze za účelem opravy některých podrobností standardu z roku 1989 a přidání rozsáhlejší podpory pro mezinárodní znakové sady. Norma prošla další revizí na konci devadesátých let, což vedlo k vydání ISO/IEC 9899: 1999 v roce 1999, která byla přijata jako norma ANSI v květnu 2000. Jazyk definovaný touto verzí normy se běžně označuje jako „ C99 ". Mezinárodní normu C udržuje pracovní skupina ISO/IEC JTC1/SC22 /WG14.

Design

1999 ISO C.pdf

C99 je z větší části zpětně kompatibilní s C89, ale v některých ohledech je přísnější.

Zejména deklarace, která postrádá specifikátor typu, již intimplicitně nepředpokládala. Výbor pro standardy C rozhodl, že pro kompilátory má větší hodnotu diagnostikovat neúmyslné vynechání specifikátoru typu, než bezobslužně zpracovávat starší kód, který spoléhá na implicitní int. V praxi kompilátory pravděpodobně zobrazí varování, poté předpokládají inta pokračují v překládání programu.

C99 představil několik nových funkcí, z nichž mnohé již byly implementovány jako rozšíření v několika kompilátorech:

Části standardu C99 jsou součástí aktuální verze standardu C ++ , včetně celočíselných typů, záhlaví a funkcí knihovny. Pole s proměnnou délkou mezi tyto zahrnuté části nepatří, protože standardní knihovna šablon C ++ již obsahuje podobné funkce.

Podpora IEEE 754 s plovoucí desetinnou čárkou

Hlavní vlastností C99 je numerická podpora, a zejména podpora přístupu k funkcím hardwaru s plovoucí desetinnou čárkou IEEE 754-1985 (také známého jako IEC 60559) přítomného v drtivé většině moderních procesorů (definováno v "Příloze F" Aritmetika s pohyblivou řádovou čárkou podle IEC 60559 “). Platformy bez hardwaru IEEE 754 jej mohou také implementovat do softwaru.

Na platformách s plovoucí desetinnou čárkou IEEE 754:

  • floatje definován jako jednoduchá přesnost IEEE 754 , doubleje definován jako dvojitá přesnost a long doubleje definován jako rozšířená přesnost IEEE 754 (např. 80bitová dvojitá rozšířená přesnost Intel na platformách x86 nebo x86-64 ) nebo nějaká forma čtyřnásobné přesnosti, je -li k dispozici; jinak je to dvojnásobná přesnost.
  • Čtyři aritmetické operace a odmocnina jsou správně zaokrouhleny podle definice IEEE 754.
    FLT_EVAL_METHOD plovák dvojnásobek dlouhý dvojník
    0 plovák dvojnásobek dlouhý dvojník
    1 dvojnásobek dvojnásobek dlouhý dvojník
    2 dlouhý dvojník dlouhý dvojník dlouhý dvojník
  • Vyhodnocení výrazu je definováno tak, aby bylo provedeno jednou ze tří dobře definovaných metod, což indikuje, zda jsou proměnné s plovoucí desetinnou čárkou ve výrazech nejprve povýšeny na přesnější formát: FLT_EVAL_METHOD == 2označuje, že všechny interní mezilehlé výpočty jsou standardně prováděny s vysokou přesností (dlouhé dvojité) pokud je k dispozici (např. 80bitový dvojitě rozšířený ), FLT_EVAL_METHOD == 1provede všechny interní mezilehlé výrazy s dvojitou přesností (pokud není operand dlouhý dvojitý), přičemž FLT_EVAL_METHOD == 0určuje, že každá operace je hodnocena pouze s přesností nejširšího operandu každého operátora. Typ mezilehlého výsledku pro operandy dané přesnosti jsou shrnuty v sousední tabulce.

FLT_EVAL_METHOD == 2má tendenci omezovat riziko zaokrouhlování chyb ovlivňujících numericky nestabilní výrazy (viz odůvodnění návrhu IEEE 754 ) a je navrženou výchozí metodou pro hardware x87 , ale poskytuje neintuitivní chování pro neopatrného uživatele; FLT_EVAL_METHOD == 1byla výchozí metoda hodnocení původně používaná v K&R C , která propagovala všechny plováky na zdvojnásobení výrazů; a FLT_EVAL_METHOD == 0také se běžně používá a určuje přísné "vyhodnotit podle typu" operandů. (Pro gcc , FLT_EVAL_METHOD == 2je výchozí na 32 bit x86, a FLT_EVAL_METHOD == 0je výchozí na 64 bit x86-64, ale FLT_EVAL_METHOD == 2může to být uvedeno na x86-64 s možností -mfpmath = 387). Před C99, překladače mohl projet mezivýsledky nekonzistentně, a to zejména při použití hardwaru s plovoucí desetinnou čárkou x87 , což vede k chování konkrétního kompilátoru; takové nesrovnalosti nejsou povoleny u překladačů vyhovujících C99 (příloha F).

Příklad

Následující komentovaný příklad kódu C99 pro výpočet funkce pokračování zlomku ukazuje hlavní funkce:

#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;
}

Poznámky pod čarou:

  1. Zkompilovat s: gcc -std=c99 -mfpmath=387 -o test_c99_fp -lm test_c99_fp.c
  2. Protože se v této funkci manipulují se stavovými příznaky IEEE 754, je tato #pragma potřebná, aby kompilátor při optimalizaci nesprávně nesestavil takové testy. (Pragmas jsou obvykle definovány implementací, ale ty s předponou STDCjsou definovány ve standardu C.)
  3. C99 definuje omezený počet metod hodnocení výrazu: aktuální režim kompilace lze zkontrolovat, aby se zajistilo, že splňuje předpoklady, pod které byl kód napsán.
  4. Lze testovat a nastavovat speciální hodnoty, jako je NaN a pozitivní nebo negativní nekonečno.
  5. long doubleje definován jako IEEE 754 s dvojnásobně rozšířenou nebo čtyřnásobnou přesností, je -li k dispozici. Použití vyšší přesnosti, než je požadováno u přechodných výpočtů, může minimalizovat chyby zaokrouhlení ( typedef double_t lze použít pro kód, který je přenosný pod všemi FLT_EVAL_METHODs).
  6. Hlavní funkce, která se má vyhodnotit. Ačkoli se zdá, že některé argumenty k tomuto pokračujícímu zlomku, např. 3,0, by vedly k chybě dělení nulou, ve skutečnosti je funkce dobře definována na 3,0 a dělení 0 jednoduše vrátí +nekonečno, které pak správně vést ke konečnému výsledku: IEEE 754 je definován tak, aby ve výchozím nastavení nezachytával takové výjimky, a je navržen tak, aby je bylo možné velmi často ignorovat, jako v tomto případě. (Pokud FLT_EVAL_METHODje definován jako 2, pak budou všechny interní výpočty včetně konstant prováděny s dlouhou dvojitou přesností; pokud FLT_EVAL_METHODje definováno jako 0, pak je třeba zajistit další péči, včetně případných dalších přetypování a explicitní specifikace konstant jako dlouhých dvojitých.)
  7. Vzhledem k tomu, že zvýšený příznak dělení nulou není v tomto případě chybou, lze jej jednoduše zrušit, aby byl příznak vymazán pro použití v pozdějším kódu.
  8. V některých případech mohou být jiné výjimky považovány za chybu, například přetečení (i když ve skutečnosti lze ukázat, že v tomto případě k tomu nemůže dojít).
  9. __STDC_IEC_559__ je definován pouze tehdy, pokud je kompilátor a knihovna C plně implementován „aritmetika s plovoucí desetinnou čárkou podle přílohy F IEC 60559“ (uživatelé by si měli být vědomi toho, že toto makro je někdy definováno, i když by nemělo být).
  10. Výchozí režim zaokrouhlení je u IEEE 754 zaokrouhlen na nejbližší (s pravidlem rovnoměrného zaokrouhlování v půli cesty), ale lze explicitně použít režim zaokrouhlení směrem k + a - nekonečnu (definováním TEST_NUMERIC_STABILITY_UPatd. V tomto případě při ladění) diagnostikovat numerickou nestabilitu. Tuto metodu lze použít, i když compute_fn()je součástí samostatně kompilované binární knihovny. Ale v závislosti na funkci nelze vždy zjistit numerické nestability.

Detekce verzí

Standardní makro __STDC_VERSION__je definováno s hodnotou, 199901Lkterá označuje, že je k dispozici podpora C99. Stejně jako u __STDC__makra pro C90 __STDC_VERSION__lze použít k zápisu kódu, který se bude kompilovat odlišně pro kompilátory C90 a C99, jako v tomto příkladu, který zajišťuje, že inlineje k dispozici v obou případech (jeho nahrazením staticv C90, aby se předešlo chybám linkeru).

#if __STDC_VERSION__ >= 199901L
  /* "inline" is a keyword */
#else
# define inline static
#endif

Implementace

Většina kompilátorů C poskytuje podporu alespoň pro některé funkce uvedené v C99.

Microsoft historicky pomalu implementoval nové funkce C do svých nástrojů Visual C ++ , místo toho se soustředil hlavně na podporu vývoje standardů C ++. Nicméně se zavedením Visual C ++ 2013 Microsoft implementoval omezenou podmnožinu C99, která byla rozšířena v Visual C ++ 2015.

Budoucí práce

Od ratifikace standardu 1999 C připravila pracovní skupina pro standardy technické zprávy specifikující vylepšenou podporu pro vložené zpracování, další datové typy znaků ( podpora Unicode ) a funkce knihovny s vylepšenou kontrolou hranic . Pokračují práce na technických zprávách řešících desetinnou čárku , další speciální matematické funkce a další funkce dynamické alokace paměti . Výbory pro standardy C a C ++ spolupracují na specifikacích pro programování závitů .

Další revize normy C, C11 , byla ratifikována v roce 2011. Výbor pro normy C přijal pokyny, které omezovaly přijímání nových funkcí, které nebyly testovány stávajícími implementacemi. Mnoho úsilí bylo vynaloženo na vývoj paměťového modelu , aby se vyjasnily body sekvence a aby se podporovalo programování závitů .

Viz také

Reference

Další čtení

externí odkazy

Předchází
C89 / C90 / "ANSI C"
Jazykové standardy C. Uspěl
C11