Printf

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2015. április 5-én felülvizsgált verziótól ; az ellenőrzések 72 szerkesztést igényelnek .

printf (az angol  print formatted , "formázott nyomtatás" szóból) - a szabványos vagy jól ismert kereskedelmi könyvtárak, illetve egyes programozási nyelvek formázott kimenetre használt beépített operátorainak függvény- vagy módszercsaládjának általánosított neve  - kimenet különböző típusú , adott sablon szerint formázott értékfolyamokhoz . Ezt a sablont egy speciális szabályok szerint összeállított karakterlánc (formátumkarakterlánc) határozza meg.

Ennek a családnak a legfigyelemreméltóbb tagja a printf függvény , valamint számos más függvény, amely printfa C szabványkönyvtár nevéből származik (amely szintén a C++ és Objective-C szabványkönyvtárak része ).

A UNIX operációs rendszerek családja rendelkezik egy printf segédprogrammal is , amely a formázott kimenet ugyanazokat a célokat szolgálja.

A Fortran FORMAT operátora egy ilyen függvény korai prototípusának tekinthető . A karakterlánc-vezérelt következtetési függvény a C nyelv előfutáraiban ( BCPL és B ) jelent meg. A C standard könyvtár specifikációjában megkapta a legismertebb formáját (jelzőkkel, szélességgel, pontossággal és mérettel). A kimeneti sablon karakterláncának szintaxisát (ezt néha formátumkarakterláncnak , formátumkarakterláncnak vagy formátumkarakterláncnak nevezik ) később más programozási nyelvek is használták (a nyelvek jellemzőinek megfelelő változatokkal). Általában ezeknek a nyelveknek a megfelelő funkcióit printf -nek és/vagy származékainak is nevezik.

Néhány újabb programozási környezet (például a .NET ) szintén használja a formátum karakterlánc-vezérelt kimenet fogalmát, de eltérő szintaxissal.

Történelem

Megjelenés

A Fortrannak már voltak operátoraim, amelyek formázott kimenetet biztosítottak. A WRITE és PRINT utasítások szintaxisa tartalmazott egy címkét, amely egy formátumspecifikációt tartalmazó, nem végrehajtható FORMAT utasításra utalt . A specifikációk az operátor szintaxisának részét képezték, és a fordító azonnal képes volt olyan kódot generálni, amely közvetlenül végrehajtja az adatformázást, ami a legjobb teljesítményt biztosította az akkori számítógépeken. Ennek ellenére a következő hátrányok voltak:

A jövőbeli printf függvény első prototípusa az 1960 -as években jelent meg a BCPL nyelven . A WRITEF függvény egy formátumkarakterláncot vesz fel, amely a karakterlánc változóban magától az adattól külön határozza meg az adattípust (a típust zászlók, szélesség, pontosság és méret mezők nélkül adták meg, de már egy százalékjel előzte meg ). [1] A formátumkarakterlánc fő célja argumentumtípusok átadása volt (a statikus gépeléssel rendelkező programozási nyelvekben az átadott argumentum típusának meghatározása egy nem rögzített formális paraméterlistával rendelkező függvénynél bonyolult és nem hatékony mechanizmust igényel típusinformáció átadására általános esetben). Maga a WRITEF függvény a kimenet egyszerűsítését szolgálta: a WRCH ( karakter kiírása), WRITES (karakterláncot), WRITEN , WRITED , WRITEOCT , WRITEHEX (számok különböző formájú kimenete) függvénykészlet helyett egyetlen hívás használták, amelyben lehetséges volt "csak szöveget" a kimeneti értékekkel átlapolni. %

Az 1969 -ben ezt követő Bee nyelv már a printf nevet használta egy egyszerű formátumú karakterlánccal (hasonlóan a BCPL -hez ), amely három lehetséges típus és két számábrázolás közül csak egyet adott meg: decimális ( %d), oktális ( %o), karakterláncok ( %s) és karakterek ( %c), és ezekben a függvényekben a kimenet formázásának egyetlen módja az volt, hogy karaktereket adunk a változó értékének kimenete előtt és után. [2]

C és származékai

A C nyelv első változatának bevezetése ( 1970 ) óta a printf család a fő formátumkimeneti eszközzé vált. A formátumkarakterlánc egyes függvényhívásokkal történő elemzésének költségét elfogadhatónak ítélték, és az egyes típusokhoz külön-külön alternatív hívások nem kerültek be a könyvtárba. A funkcióspecifikáció mindkét létező , 1990 -ben és 1999 -ben kiadott nyelvi szabványban szerepelt . Az 1999-es specifikáció néhány újítást tartalmaz az 1990-es specifikációból.

A C++ nyelv a szabványos C könyvtárat használja (az 1990-es szabvány szerint), beleértve a teljes printf családot .

Alternatív megoldásként a C++ szabványos könyvtár folyam bemeneti és kimeneti osztályokat biztosít. Ennek a könyvtárnak a kimeneti utasításai típusbiztosak, és nem igényelnek formátum karakterlánc-elemzést minden egyes meghívásakor. Sok programozó azonban továbbra is a printf családot használja , mivel a kimeneti sorrend velük általában kompaktabb, és a használt formátum lényege világosabb.

Az Objective-C egy meglehetősen "vékony" kiegészítő a C-hez, és a rajta lévő programok közvetlenül használhatják a printf család funkcióit .

Használat más programozási nyelveken

A C-n és származékain (C++, Objective-C) kívül sok más programozási nyelv is használja a printf-szerű formátumú karakterlánc-szintaxist:

Ezenkívül a legtöbb UNIX-szerű rendszerben található printf segédprogramnak köszönhetően a printf számos shell szkriptben használatos ( sh , bash , csh , zsh stb. esetén).

Követők

Néhány újabb nyelv és programozási környezet is használja a formátum karakterlánc-vezérelt kimenet fogalmát, de eltérő szintaxissal.

Például a .Net Core Class Library (FCL) a System.String.Format , System.Console.Write és System.Console.WriteLine metóduscsaláddal rendelkezik , amelyek némelyik túlterhelése egy formátum karakterlánc szerint adja ki az adatokat. Mivel az objektumtípusokról teljes információ áll rendelkezésre a .Net futtatókörnyezetben, nem szükséges ezeket az információkat a formátumkarakterláncban átadni.

Családi függvény elnevezése

Minden függvény nevében szerepel a printf szár . A függvény neve előtti előtagok jelentése:

Általános egyezmények

Minden függvény egy formátum karakterláncot vesz fel az egyik paraméterként ( format ) (a karakterlánc szintaxisának leírása alább). A kiírt (kinyomtatott) karakterek számát adja vissza , a végén lévő null karaktert nem számítva . A formázott kimenethez adatokat tartalmazó argumentumok számának legalább annyinak kell lennie, amennyi a formátum karakterláncban szerepel. Az "extra" argumentumokat figyelmen kívül hagyja.

Az n családfüggvény ( snprintf , vsnprintf ) visszaadja a kinyomtatott karakterek számát, ha az n paraméter (a nyomtatandó karakterek számának korlátozása) elég nagy lenne. Egybájtos kódolás esetén a visszatérési érték a karakterlánc kívánt hosszának felel meg (nem számítva a végén lévő null karaktert).

Az s család függvényei ( sprintf , snprintf , vsprintf , vsnprintf ) első paraméterükként egy mutatót vesznek fel arra a memóriaterületre, ahová az eredményül kapott karakterláncot írjuk. Azok a függvények, amelyek nem korlátozzák a kiírt karakterek számát, nem biztonságos funkciók, mivel puffertúlcsordulási hibához vezethetnek, ha a kimeneti karakterlánc nagyobb, mint a kimenethez lefoglalt memória mérete.

Az f család függvényei bármilyen nyitott adatfolyamba írnak egy karakterláncot (az adatfolyam paramétert ), különösen a szabványos kimeneti folyamokra ( stdout , stderr ). fprintf(stdout, format, …)-vel egyenértékű printf(format, …).

A v család függvényei az argumentumokat nem változó számú argumentumként veszik fel (mint az összes többi printf függvény), hanem listának va list . Ebben az esetben a függvény meghívásakor a va end makró nem kerül végrehajtásra.

A w (első karakter) család függvényei az s függvénycsalád korlátozott Microsoft implementációi : wsprintf , wnsprintf , wvsprintf , wvnsprintf . Ezek a funkciók a user32.dll és shlwapi.dll dinamikus könyvtárakban vannak megvalósítva ( n függvény). Nem támogatják a lebegőpontos kimenetet, a wnsprintf és a wvnsprintf pedig csak balra igazított szöveget támogat.

A w család funkciói ( wprintf , swprintf ) a többbyte-os kódolások támogatását valósítják meg, ennek a családnak minden funkciója többbyte-os karakterláncokra mutató mutatókkal ( wchar_t ) működik.

Az a család függvényei ( asprintf , vasprintf ) a malloc függvény segítségével foglalnak le memóriát a kimeneti karakterlánchoz , a memória felszabadul a hívási eljárás során, a függvény végrehajtása közbeni hiba esetén a memória nem kerül lefoglalásra.

A funkciók leírása

Paraméternevek

A funkciók leírása

Visszatérési érték: negatív érték — hibajel; ha sikeres, akkor a függvények visszaadják az írt/kimeneti bájtok számát (a végén a null byte-ot figyelmen kívül hagyva), az snprintf függvény pedig azt a bájtok számát írja ki, ami akkor lenne kiírva, ha n elég nagy lenne.

Az snprintf meghívásakor n lehet nulla (ez esetben s lehet null pointer ), ilyenkor nem történik írás, a függvény csak a helyes visszatérési értéket adja vissza.

Formátum karakterlánc szintaxis

C-ben és C++-ban a formátum karakterlánc null-végződésű karakterlánc. A formátum-meghatározók kivételével minden karaktert a rendszer változatlanul átmásol a kapott karakterláncba. A formátummeghatározó elejének standard jele a karakter %( Percent sign ), magának a jelnek a megjelenítéséhez %annak megkettőzését használjuk %%.

A formátummeghatározó szerkezete

A formátum megadása így néz ki:

% [ zászlók ][ szélesség ][ . pontosság ][ méret ] típus

A szükséges összetevők a formátummeghatározó kezdő karaktere ( %) és a típus .

Flags
Jel Aláírási név Jelentése Ennek a jelnek a hiányában jegyzet
- mínusz a kimeneti érték balra van igazítva a minimális mezőszélességen belül jobbra
+ egy plusz mindig adjon meg egy jelet (plusz vagy mínusz) a megjelenített decimális számértékhez csak negatív számok esetén
  tér Tegyen szóközt az eredmény elé, ha az érték első karaktere nem előjel A kimenet számmal kezdődhet. A + karakter elsőbbséget élvez a szóköz karakterrel szemben. Csak előjeles decimális értékekhez használatos.
# rács értékkiadás „alternatív formája”. Ha számokat hexadecimális vagy oktális formátumban ad ki, a számot egy formátumjellemző (0x vagy 0) előzi meg.
0 nulla töltse be a mezőt a jellel az escape szekvencia szélessége mezőben megadott szélességre0 betét szóközökkel A d , i , o , u , x , X , a , A , e , E , f , F , g , G típusokhoz használatos . A d , i , o , u , x , X típusoknál a pontosság megadása esetén ez a jelző figyelmen kívül marad. Más típusok esetében a viselkedés nem definiált.

Ha mínusz '-' jelző van megadva, akkor ezt a jelzőt is figyelmen kívül hagyja.

Szélesség módosító

A Width (tizedes vagy csillag karakter ) a mező minimális szélességét adja meg (beleértve a számok előjelét is). Ha az értékmegjelenítés nagyobb, mint a mező szélessége, akkor a bejegyzés a mezőn kívül esik (például a %2i 100-as érték esetén három karakteres mezőértéket ad), ha az értékábrázolás kisebb, mint a megadott szám, akkor ez (alapértelmezés szerint) szóközökkel lesz kitöltve a bal oldalon, a viselkedés a többi beállított jelzőtől függően változhat. Ha egy csillag van megadva szélességként, akkor a mező szélességét az argumentumlistában a kimeneti érték előtt kell megadni (például printf( "%0*x", 8, 15 );szöveget jelenít meg 0000000f). Ha negatív szélességmódosítót adunk meg ilyen módon, akkor a - jelzőt beállítottnak tekintjük , és a szélesség módosító értékét abszolút értékre állítjuk.

Pontosság módosító
  • jelzi a karakterek minimális számát, amelynek meg kell jelennie a d , i , o , u , x , X típusok feldolgozásakor ;
  • jelzi a karakterek minimális számát, amelynek a tizedesvessző (pont) után kell megjelennie az a , A , e , E , f , F típusok feldolgozása során ;
  • a g és G típusok jelentős karaktereinek maximális száma ;
  • az s típushoz nyomtatható karakterek maximális száma ;

A pontosság egy pont, amelyet egy tizedes szám vagy egy csillag ( * ) követ, ha nincs szám vagy csillag (csak egy pont van jelen), akkor a szám nullának számít. A pont a pontosság jelzésére szolgál még akkor is, ha vessző jelenik meg a lebegőpontos számok kiírásakor.

Ha a pont után csillag karakter van megadva, akkor a formátum karakterlánc feldolgozása során a mező értéke az argumentumlistából kerül kiolvasásra. (Ugyanakkor, ha a csillag karakter a szélesség mezőben és a precíziós mezőben is szerepel, először a szélesség jelenik meg, majd a pontosság, és csak azután a kimenet értéke). Például printf( "%0*.*f", 8, 4, 2.5 );megjeleníti a szöveget 002.5000. Ha negatív precíziós módosító van így megadva, akkor nincs precíziós módosító. [19]

Méretmódosító

A méret mező lehetővé teszi a függvénynek átadott adatok méretének megadását. Ennek a mezőnek a szükségességét a függvénynek tetszőleges számú paraméter átadásának sajátosságai magyarázzák a C nyelvben: a függvény nem tudja "önállóan" meghatározni az átvitt adatok típusát és méretét, így a paraméterek típusáról és azok méretéről szóló információ. a pontos méretet kifejezetten meg kell adni.

Figyelembe véve a méretmeghatározások hatását az egész számok formázására, meg kell jegyezni, hogy a C és C++ nyelvekben előjeles és előjel nélküli egész típusok párjainak láncolata létezik, amelyek a méretek nem csökkenő sorrendjében a következőképpen rendezve:

aláírt típus Aláíratlan típus
aláírt char előjel nélküli char
aláírt rövid ( rövid ) unsigned short int ( unsigned short )
aláírt int ( int ) unsigned int ( unsigned )
hosszú int ( hosszú ) unsigned long int ( unsigned long )
hosszú hosszú int ( hosszú hosszú ) unsigned long long int ( unsigned long long )

A típusok pontos mérete nem ismert, kivéve az előjeles char és az előjel nélküli char típusokat .

A páros előjeles és előjel nélküli típusok mérete megegyezik, és a mindkét típusban reprezentálható értékek ugyanazt a reprezentációt tartalmazzák.

A char típus mérete megegyezik az előjeles és az előjel nélküli karaktertípusokkal , és megosztja a reprezentálható értékek halmazát ezen típusok egyikével. Feltételezzük továbbá, hogy a char  egy másik neve ezen típusok egyikének; egy ilyen feltételezés a jelen megfontolás szempontjából elfogadható.

Ezenkívül a C a _Bool típussal rendelkezik , míg a C++ a bool típusú .

Amikor argumentumokat adunk át egy függvénynek, amelyek nem felelnek meg a függvény prototípusának formális paramétereinek (melyek mindegyik argumentum kimeneti értékeket tartalmaz), ezek az argumentumok szabványos előléptetéseken mennek keresztül , nevezetesen:

  • a float argumentumok duplázásra kerülnek ;
  • az unsigned char , unsigned short , signed char és short típusú argumentumok a következő típusok egyikébe kerülnek:
    • int , ha ez a típus képes az eredeti típus összes értékének megjelenítésére, vagy
    • egyébként aláíratlan ;
  • A _Bool vagy bool típusú argumentumok az int típusba kerülnek .

Így a printf függvények nem vehetnek fel float , _Bool vagy bool típusú argumentumokat, illetve int vagy unsigned típusú integer típusú argumentumokat .

A használt méretmeghatározók készlete a típusleírótól függ (lásd alább).

meghatározó %d, %i, %o, %u, %x,%X %n jegyzet
hiányzó int vagy unsigned int mutató int
l long int vagy unsigned long int mutató hosszú int
hh Az argumentum int vagy unsigned int típusú , de kénytelen beírni: signed char vagy unsigned char mutató az előjeles karakterre formálisan a C nyelven az 1999-es szabvány óta, a C++-ban pedig a 2011-es szabvány óta létezik.
h Az argumentum int vagy unsigned int típusú , de kénytelen beírni a short int vagy unsigned short int mutató rövid int
ll long long int vagy unsigned long long int pointer long long int
j intmax_t vagy uintmax_t mutató intmax_t
z size_t (vagy mérettel egyenértékű aláírt típus) mutasson egy előjeles típusra , amely méretében megegyezik a size_t mérettel
t ptrdiff_t (vagy ezzel egyenértékű, előjel nélküli típus) mutasson a ptrdiff_t -re
L __int64 vagy aláírás nélküli __int64 mutató az __int64 -re Borland Builder 6 esetén (a specifikátor ll32 bites számot vár)

A specifikációk hés hha szabványos típusú promóciók kompenzálására szolgálnak az aláírt típusról az aláíratlan típusra való átmenetekkel együtt, vagy fordítva.

Vegyünk például egy C-megvalósítást, ahol a char típus előjeles és 8 bites, az int típusé 32 bites, és a negatív egészek kódolásának egy további módja van.

char c = 255 ; printf ( "%X" , c );

Egy ilyen hívás kimenetet produkál FFFFFFFF, ami nem biztos, hogy azt a programozó várta. Valójában c értéke (char)(-1) , a típuspromóció után pedig -1 . A formátum alkalmazása %Xa megadott értéket előjel nélküliként értelmezi, azaz 0xFFFFFFFF .

char c = 255 ; printf ( "%X" , ( unsigned char ) c ); char c = 255 ; printf ( "%hhX" , c );

Ez a két hívás ugyanazt a hatást fejti ki, és a kimenetet hozza létre FF. Az első opció lehetővé teszi az előjel-szorzás elkerülését a típus népszerűsítésekor, a második pedig már a printf függvényben "belül" kompenzálja azt .

meghatározó %a, %A, %e, %E, %f, %F, %g,%G
hiányzó kettős
L hosszú dupla
meghatározó %c %s
hiányzó Az argumentum int vagy unsigned int típusú , de kénytelen beírni a char parancsot char*
l Az argumentum wint_t típusú , de kénytelen beírni a wchar_t wchar_t*
Típusmeghatározó

A típus nem csak az érték típusát jelzi (a C programozási nyelv szempontjából), hanem a kimeneti érték konkrét ábrázolását is (például a számok decimális vagy hexadecimális formában jeleníthetők meg). Egyetlen karakterként írva. Más mezőkkel ellentétben kötelező. Az egyetlen escape szekvencia maximális támogatott kimeneti mérete szabvány szerint legalább 4095 karakter; a gyakorlatban a legtöbb fordítóprogram lényegesen nagyobb adatmennyiséget támogat.

Típusértékek:

  • d , i  — előjeles decimális szám, alapértelmezett típusa int . Alapértelmezés szerint jobbra igazítással írják, az előjelet csak negatív számokra írják. A scanf család függvényeivel ellentétben a printf család függvényei esetében a %d és %i specifikációk teljesen szinonimák;
  • o  — előjel nélküli oktális szám, az alapértelmezett típus unsigned int ;
  • u  egy előjel nélküli decimális szám, az alapértelmezett típus az unsigned int ;
  • x és X  előjel nélküli hexadecimális számok, x kis betűket használ (abcdef), X nagy betűket (ABCDEF), alapértelmezett típusa előjel nélküli int ;
  • f és F  lebegőpontos számok, az alapértelmezett típus a double . Alapértelmezés szerint 6-os pontossággal adják ki, ha a modulszám kisebb, mint egy, akkor a tizedespont elé 0 kerül. A ±∞ értékek [-]inf vagy [-]végtelen formában jelennek meg (platformtól függően); a Nan értéke [-]nan vagy [-]nan (bármilyen szöveg alább) . Az F használata nagybetűkkel nyomtatja ki a megadott értékeket ( [-]INF , [-]INFINITY , NAN ).
  • e és E  lebegőpontos számok exponenciális jelöléssel (1.1e+44 alakú), az alapértelmezett típus a double . e kiírja az "e" karaktert kisbetűvel, E  - nagybetűvel (3.14E+0);
  • g és G  egy lebegőpontos szám, az alapértelmezett típus a double . Az ábrázolás formája a mennyiség értékétől ( f vagy e ) függ . A formátum kissé eltér a lebegőpontostól, mivel a tizedesvesszőtől jobbra lévő kezdő nullák nem kerülnek kiadásra. Ezenkívül a pontosvessző rész nem jelenik meg, ha a szám egész szám;
  • a és A (az 1999-es C és a 2011-es C++ nyelvi szabványokból kiindulva) — egy lebegőpontos szám hexadecimális formában, az alapértelmezett típus a double ;
  • c  — a szimbólum kiadása az átadott argumentumnak megfelelő kóddal, az alapértelmezett típus az int ;
  • s - egy karakterlánc  kimenete null lezáró bájttal; ha a hossz módosító l , akkor a wchar_t* karakterlánc kerül kiadásra . Windows rendszeren az s típus értékei a használt függvények típusától függenek. Ha printffüggvénycsaládot használunk, akkor s a char* karakterláncot jelöli . Ha wprintffüggvénycsaládot használunk, akkor s a wchar_t* karakterláncot jelöli .
  • S  ugyanaz, mint s hosszmódosítóval l ; Windows rendszeren az S típus értéke a használt függvények típusától függ. Ha printffüggvénycsaládot használunk, akkor S a wchar_t* karakterláncot jelöli . Ha wprintffüggvénycsaládot használunk, akkor S a char* karakterláncot jelöli .
  • p - pointer  kimenet , a megjelenés jelentősen változhat a fordító és a platform belső megjelenítésétől függően (például a 16 bites MS-DOS platform az űrlap jelölését használja FFEC:1003, a 32 bites lapos címzésű platform pedig a címet az űrlapról 00FA0030);
  • n - mutatónkénti rekord, argumentumként átadva, az n  -t tartalmazó parancssorozat előfordulásakor írt karakterek száma ;
  • %  - karakter a százalékjel (%) megjelenítéséhez, amely lehetővé teszi a százalékkarakterek kiadását a printf karakterláncban, mindig az űrlapban %%.
Lebegőpontos számok kimenete

Az aktuális területi beállítástól függően vessző és pont (és esetleg egy másik szimbólum) is használható a lebegőpontos számok megjelenítésekor. A printf viselkedését a szám tört és egész részét elválasztó karakterhez képest a használatban lévő terület (pontosabban az LC NUMERIC változó ) határozza meg. [húsz]

Speciális makrók egész adattípusú álnevek kiterjesztett halmazához

A Second C szabvány (1999) kiterjesztett álneveket biztosít az int N _t , uint N _t , int_least N _t , uint_least N _t , int_fast N _t , uint_fast N _t (ahol N a szükséges bitmélység), intptr_t egész adattípusokhoz. , uintptr_t , intmax_t , uintmax_t .

Ezen típusok mindegyike egyezik a szabványos beépített egész típusokkal, vagy nem. Formálisan a hordozható kód írásakor a programozó nem tudja előre, hogy melyik szabványos vagy kiterjesztett méretű specifikációt kell alkalmaznia.

int64_t x = 100000000000 ; int szélesség = 20 ; printf ( "%0*lli" , szélesség , x ); Rossz, mert lehet, hogy az int64_t nem ugyanaz, mint a long long int .

Annak érdekében, hogy az ilyen típusú objektumok vagy kifejezések értékeit hordozható és kényelmes módon lehessen következtetni, a megvalósítás mindegyik típushoz meghatároz egy makrót, amelyek értékei a méret- és típusspecifikációkat kombináló karakterláncok.

A makrók nevei a következők:

Egy pár aláírt és előjel nélküli típus Makró neve
int N_t és uint N_t _ _ PRITN
int_least N _t és uint_least N _t PRITLEASTN
int_fastN_t és uint_fastN_t _ _ _ _ PRITFASTN
intmax_t és uintmax_t PRITMAX
intptr_t és uintptr_t PRITPTR

Itt T található a következő típusspecifikációk egyike: d, i, u, o, x, X.

int64_t x = 100000000000 ; int szélesség = 20 ; printf ( "%0*" PRIi64 , szélesség , x ); Az int64_t típusú érték helyes kiadása C nyelven.

Észreveheti, hogy az intmax_t és uintmax_t típusok szabványos méretmeghatározóval rendelkeznek j, így a makró valószínűleg mindig a következőképpen van megadva . PRITMAX"jT"

XSI kiterjesztések az egységes Unix szabványban

A Single UNIX szabvány szerint (amely gyakorlatilag egyenértékű a POSIX szabvánnyal ) a printf következő kiegészítései vannak meghatározva az ISO C-hez képest, az XSI (X/Open System Interface) kiterjesztés alatt:

  • A rendszer hozzáadja a tetszőleges paraméter számmal történő kiadásának lehetőségét (ezt n$közvetlenül a vezérlősorozat elejének karaktere után jelzi, például printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);).
  • Hozzáadott "'" (egy idézőjel) jelző, amely a d , i , o , u típusoknál a megfelelő karakterrel külön osztályokat ír elő.
  • C típus , amely megfelel az lc ISO C-nek ( wint_t típusú karakterkimenet ).
  • S típusú , amely egyenértékű az ls ISO C-vel (karakterlánc kimenet, például wchar_t* )
  • EILSEQ, EINVAL, ENOMEM, EOVERFLOW hibakódok hozzáadva.

Nem szabványos kiterjesztések

GNU C Library

A GNU C Library ( libc ) a következő kiterjesztéseket adja hozzá:

  • Az m típus kiírja az errno globális változó értékét (az utolsó függvény hibakódját).
  • a C típus egyenértékű az lc -vel .
  • a ' (egy idézőjel) jelzőt az osztályok elválasztására használják számok nyomtatása során. Az elválasztás formátuma a következőtől függ: LC_NUMERIC
  • a q mérete a long long int típust jelöli (azokon a rendszereken ahol a long long int nem támogatott , ez ugyanaz, mint a long int
  • A Z méret a z álneve , a C99 szabvány megjelenése előtt került be a libc-be , és nem ajánlott új kódban használni.
Saját típusok regisztrálása

A GNU libc támogatja az egyéni típusú regisztrációt, lehetővé téve a programozó számára, hogy meghatározza saját adatstruktúráihoz a kimeneti formátumot. Új típus regisztrálásához használja a függvényt
int register_printf_function (int type, printf_function handler-function, printf_arginfo_function arginfo-function), ahol:

  • type  — a típus betűjele (ha type = 'Y', akkor a hívás így fog kinézni: '%Y');
  • handler-function  - egy olyan függvényre mutató mutató, amelyet a printf függvények hívnak meg, ha a típusban megadott típus megtalálható a formátumban ;
  • Az arginfo-függvény  egy olyan függvény mutatója, amelyet a parse_printf_format függvény hív meg .

Az új típusok meghatározása mellett a regisztráció lehetővé teszi a meglévő típusok (például s , i ) újradefiniálását.

Microsoft Visual C

A Microsoft Visual Studio a C/C++ programozási nyelvekhez a printf specifikáció formátumában (és egyéb családi funkciók) a következő bővítményeket biztosítja:

  • doboz mérete:
mező értéke típusú
I32 aláírt __int32 , aláíratlan __int32
I64 aláírt __int64 , aláíratlan __int64
én ptrdiff_t , size_t
w l -vel egyenértékű karakterláncok és karakterek esetén
juhar

A Maple matematikai környezetnek van egy printf függvénye is, amely a következő tulajdonságokkal rendelkezik:

Formázás
    • %a, %A: A Maple objektum szöveges jelöléssel kerül visszaadásra, ez minden objektumnál működik (pl. mátrixok, függvények, modulok stb.). A kisbetű arra utasítja, hogy a karaktereket (neveket) backtick-ekkel vegyék körül, amelyeket a printf bemenetében backtick-ekkel kell körülvenni.
    • %q, %Q: ugyanaz, mint a %a/%A, de nem csak egy argumentum kerül feldolgozásra, hanem minden attól kezdve, amelyik megfelel a formázási jelzőnek. Így a %Q/%q jelző csak utolsóként jelenhet meg a formátum karakterláncában.
    • %m: Formázza az objektumot a belső Maple reprezentációja szerint. Gyakorlatilag változók fájlba írásához használják.

Példa:

> printf("%a =%A", `+`, `+`); `+` = + > printf("%a =%m", `+`, `+`); `+` = I"+f*6"F$6#%(builtinGF$"$Q"F$F$F$F"%*protectedG Következtetés

A Maple fprintf függvénye vagy egy fájlleírót (az fopen által visszaadott), vagy egy fájlnevet vesz fel első argumentumként. Ez utóbbi esetben a névnek „szimbólum” típusúnak kell lennie, ha a fájlnév pontokat tartalmaz, akkor azt backtick-be kell zárni, vagy konvertálni (fájlnév, szimbólum) függvénnyel.

Sebezhetőségek

A printf család függvényei az argumentumok listáját és azok méretét külön paraméterként veszik (a formátum stringben). A formátum karakterlánc és az átadott argumentumok közötti eltérés előre nem látható viselkedéshez, verem sérüléséhez, tetszőleges kódfuttatáshoz és a dinamikus memóriaterületek megsemmisüléséhez vezethet. A család számos funkcióját "unsafe"-nek ( angolul  unsafe ) nevezik, mivel még csak elméletileg sem képesek megvédeni a helytelen adatok ellen.

Ezenkívül az s család függvényei ( n nélkül , például sprintf , vsprintf ) nem korlátozzák az írt karakterlánc maximális méretét, és puffertúlcsordulási hibához vezethetnek (ha az adatokat a lefoglalt memóriaterületen kívül írják).

Viselkedés, amikor a formázási karakterlánc és az átadott argumentumok nem egyeznek

A hívási konvenció részeként a cdeclveremtisztítást a hívó funkció végzi. A printf meghívásakor az argumentumok (vagy a rájuk mutatók) a beírásuk sorrendjében (balról jobbra) kerülnek elhelyezésre. A formázási karakterlánc feldolgozása közben a printf függvény argumentumokat olvas be a veremből. A következő helyzetek lehetségesek:

  • az argumentumok száma és típusa megegyezik a formátum karakterláncában megadottakkal (normál függvényművelet)
  • több argumentum adott át a függvénynek, mint amennyit a formátum karakterláncban megadtunk (extra argumentumok)
  • Kevesebb argumentumot adott át a függvény, mint amennyit a formátum karakterlánc megkövetel (nincs elegendő argumentum)
  • Rossz méretű argumentumok adták át a függvénynek
  • A megfelelő méretű, de nem megfelelő típusú argumentumokat adtuk át a függvénynek

A C nyelvi specifikációk csak két helyzetet írnak le (normál művelet és extra argumentumok). Minden más helyzet hibás, és meghatározatlan programviselkedéshez vezet (a valóságban tetszőleges eredményekhez vezet, egészen a nem tervezett kódszakaszok végrehajtásáig).

Túl sok érv

Ha túl sok argumentumot ad át, a printf függvény beolvassa a formátum karakterlánc helyes feldolgozásához szükséges argumentumokat, és visszatér a hívó függvényhez. A hívó függvény a specifikációnak megfelelően törli a veremből a hívott függvénynek átadott paramétereket. Ebben az esetben az extra paraméterek egyszerűen nem kerülnek felhasználásra, és a program változtatás nélkül folytatódik.

Nincs elég érv

Ha a printf meghívásakor kevesebb argumentum van a veremben, mint amennyi a formázási karakterlánc feldolgozásához szükséges, akkor a hiányzó argumentumok kiolvasásra kerülnek a veremből, annak ellenére, hogy tetszőleges adat van a veremben (nem releváns a printf munkájához ). . Ha az adatfeldolgozás „sikeres” volt (azaz nem fejezte be a programot, nem lógott le vagy nem írt a verembe), a hívó függvényhez való visszatérés után a veremmutató értéke visszaáll az eredeti értékére, és a a program folytatódik.

Az "extra" veremértékek feldolgozásakor a következő helyzetek lehetségesek:

  • Egy "extra" paraméter sikeres kiolvasása a kimenethez (szám, mutató, szimbólum stb.) - a veremből kiolvasott "majdnem véletlenszerű" érték a kimeneti eredmények közé kerül. Ez nem jelent veszélyt a program működésére, de bizonyos adatok kompromittálásához vezethet (veremértékek kimenete, amellyel a támadó elemezheti a program működését, és hozzáférhet a program belső/privát információihoz).
  • Hiba a veremből való érték beolvasásakor (például a rendelkezésre álló veremértékek kimerülése vagy a "nem létező" memóriaoldalak elérése miatt) - egy ilyen hiba nagy valószínűséggel a program összeomlását okozza.
  • Paraméterre mutató mutató olvasása. A karakterláncok mutató segítségével kerülnek átadásra, amikor "tetszőleges" információkat olvasunk ki a veremből, az olvasott (majdnem véletlenszerű) értéket használjuk mutatóként egy véletlenszerű memóriaterületre. A program viselkedése ebben az esetben nem definiált, és ennek a memóriaterületnek a tartalmától függ.
  • Paraméter írása mutatóval ( %n) - ebben az esetben a viselkedés hasonló az olvasási helyzethez, de bonyolítja az tetszőleges memóriacellába írás lehetséges mellékhatásai .
Az argumentumtípus eltérése

Formálisan minden eltérés az argumentum típusa és az elvárás között a program definiálatlan viselkedését okozza. A gyakorlatban számos olyan eset van, amelyek a programozási gyakorlat szempontjából különösen érdekesek:

  • Az argumentum a várttal megegyező típusú, de eltérő méretű.
  • Az argumentum mérete megegyezik a várttal, de más típusú.

Más esetek általában nyilvánvalóan helytelen viselkedéshez vezetnek, és könnyen észlelhetők.

Egész vagy lebegőpontos argumentumméret nem egyezik

Egész argumentum esetén (egész formátum specifikációval) a következő helyzetek lehetségesek:

  • A vártnál nagyobb paraméterek átadása (a kisebb kiolvasása a nagyobbból). Ebben az esetben az elfogadott bájtsorrendtől és a verem növekedési irányától függően a megjelenített érték vagy egybeeshet az argumentum értékével, vagy kiderülhet, hogy nem kapcsolódik hozzá.
  • A vártnál kisebb paraméterek átadása (kisebbről nagyobb olvasás). Ebben az esetben egy olyan helyzet lehetséges, amikor a rendszer olyan veremterületeket olvas be, amelyek túllépik az átadott argumentumok határait. A függvény viselkedése ebben az esetben hasonló a paraméterhiányos helyzetben való viselkedéshez. Általában a kimeneti érték nem egyezik a várt értékkel.

Valódi argumentum esetén (valós formátum specifikációval), bármilyen méretbeli eltérés esetén a kimeneti érték általában nem egyezik az átadott értékkel.

Általános szabály, hogy ha valamelyik argumentum mérete hibás, akkor az összes további argumentum helyes feldolgozása lehetetlenné válik, mivel az argumentumok mutatójába hiba kerül be. Ez a hatás azonban ellensúlyozható a verem értékeinek igazításával.

Értékek igazítása a veremben

Számos platform rendelkezik egész számok és/vagy valós értékek igazítási szabályaival, amelyek megkövetelik (vagy javasolják), hogy azokat a méretük többszörösének megfelelő címeken helyezzék el. Ezek a szabályok a függvényargumentumok veremben való átadására is vonatkoznak. Ebben az esetben a várt és a tényleges paraméterek típusaiban előforduló számos eltérés észrevétlen marad, ami a megfelelő program illúzióját keltheti.

uint32_t a = 1 ; uint64_t b = 2 , c = 3 ; printf ( "%" PRId64 "%" PRId64 "%" PRId64 , b , a , c ); Ebben a példában a tényleges atípusparaméterhez uint32_térvénytelen formátumspecifikáció %"PRId64"tartozik a típushoz uint64_t. Egyes 32 bites típusú platformokon azonban intaz elfogadott bájtsorrendtől és a verem növekedési irányától függően a hiba észrevétlen maradhat. A tényleges bés paraméterek cegy olyan címhez lesznek igazítva, amely a méretük többszöröse (a méret kétszerese a). Az értékek „között” pedig aegy b32 bites üres (általában nullázott) hely marad; az anyagjegyzék feldolgozása során a %"PRId64"32 bites érték aezzel a szóközzel együtt egyetlen 64 bites értékként értelmeződik.

Ilyen hiba váratlanul megjelenhet a programkód másik platformra történő portolásakor, a fordító vagy a fordítási mód megváltoztatásakor.

Lehetséges méreteltérés

A C és C++ nyelvek definíciói csak az adattípusok méretére és megjelenítésére vonatkozó legáltalánosabb követelményeket írják le. Ezért sok platformon néhány formálisan eltérő adattípus ábrázolása megegyezik. Emiatt bizonyos típusú eltérések hosszú ideig észrevétlenek maradnak.

Például a Win32 platformon általánosan elfogadott, hogy a és típusok mérete intmegegyezik long int(32 bit). Így a printf("%ld", 1)vagy a hívás printf("%d", 1L)„helyesen” végrehajtásra kerül.

Ilyen hiba váratlanul megjelenhet a programkód másik platformra történő portolásakor, a fordító vagy a fordítási mód megváltoztatásakor.

A C++ nyelvű programok írásakor ügyelni kell az egész típusú álnevekkel deklarált változók értékeinek származtatására, különösen a size_t, és ptrdiff_t; a C++ szabványkönyvtár formális definíciója az első C szabványra (1990) utal. A második C szabvány (1999) méretspecifikációkat határoz meg a típusokhoz size_tés számos más típushoz hasonló objektumokkal való használatra. ptrdiff_tSok C++ implementáció is támogatja őket.

méret_t s = 1 ; printf ( "%u" , s ); Ez a példa egy olyan hibát tartalmaz, amely olyan platformokon fordulhat elő, sizeof (unsigned int)ahol sizeof (size_t). méret_t s = 1 ; printf ( "%zu" , s ); A típusobjektum értékére a helyes következtetés a size_tC nyelv. Típushiba, ha a méret megegyezik

Ha az átadott argumentumok azonos méretűek, de eltérő típusúak, akkor a program gyakran "majdnem helyesen" fog futni (nem okoz memóriaelérési hibákat), bár a kimeneti érték valószínűleg értelmetlen. Meg kell jegyezni, hogy a páros egész típusok (előjeles és előjel nélküli) keverése megengedett, nem okoz definiálatlan viselkedést, és néha szándékosan használják a gyakorlatban.

Formátumspecifikáció használatakor a rendszer a karakterlánc címétől %seltérő egész, valós vagy mutató típusú argumentumértéket char*értelmezi a karakterlánc címeként. Ez a cím általánosságban tetszőlegesen mutathat egy nem létező vagy hozzáférhetetlen memóriaterületre, ami memóriaelérési hibához vezet, vagy olyan memóriaterületre, amely nem tartalmaz sort, ami értelmetlen kimenetet eredményez, esetleg nagyon nagy .

Formázási karakterlánc sebezhetősége

Mivel a printf (és a család többi funkciója) változtatás nélkül tudja kiadni a formátum karakterlánc szövegét, ha nem tartalmaz escape szekvenciákat, akkor lehetséges a parancs általi szövegkiadás
printf(text_to_print);
Ha a text_to_print külső forrásból származik (fájlból olvasható , amelyet a felhasználótól vagy az operációs rendszertől kaptunk), akkor a százalékjel jelenléte a kapott karakterláncban rendkívül nemkívánatos következményekkel járhat (a program lefagyásáig).

Példa hibás kódra:
printf(" Current status: 99% stored.");
Ez a példa egy „% s” escape szekvenciát tartalmaz, amely az escape szekvencia karaktert (%), egy jelzőt (szóköz) és egy karakterlánc adattípust ( s ) tartalmaz. A függvény, miután megkapta a vezérlőszekvenciát, megpróbálja beolvasni a stringre mutató mutatót a veremből. Mivel nem adtak át további paramétereket a függvénynek, a veremből kiolvasandó érték nincs meghatározva. Az eredményül kapott értéket a rendszer egy null-végződésű karakterláncra mutató mutatóként értelmezi. Egy ilyen "karakterlánc" kimenete tetszőleges memóriakiíratáshoz, memóriaelérési hibához és veremsérüléshez vezethet. Az ilyen típusú sebezhetőséget formátumkarakterlánc - támadásnak nevezik .  [21]

Puffer túlcsordulás

A printf függvényt eredmény kiírásakor nem korlátozza a kimeneti karakterek maximális száma. Ha egy hiba vagy tévedés következtében a vártnál több karakter jelenik meg, a legrosszabb, ami történhet, a kép „megsemmisülése” a képernyőn. A printf analógiájával létrehozott sprintf függvényt sem korlátozták a kapott karakterlánc maximális méretében. A „végtelen” termináltól eltérően azonban az alkalmazás által a kapott karakterlánchoz lefoglalt memória mindig korlátozott. Az elvárt határok túllépése esetén pedig más adatstruktúrákhoz tartozó memóriaterületeken (illetve általában nem elérhető memóriaterületeken) történik a rögzítés, ami azt jelenti, hogy szinte minden platformon összeomlik a program. A memória tetszőleges területeire való írás előre nem látható hatásokhoz vezet (amelyek sokkal később jelentkezhetnek, és nem programhiba, hanem felhasználói adatok sérülése formájában). A maximális karakterláncméret korlátozásának hiánya alapvető tervezési hiba a függvény fejlesztése során. Emiatt a sprintf és a vsprintf függvények nem biztonságos állapotúak . Ehelyett kifejlesztette az snprintf , vsnprintf függvényeket , amelyek egy további argumentumot vesznek fel, amely korlátozza a maximális eredő karakterláncot. A jóval később megjelent swprintf függvény (többbyte -os kódolásokhoz) figyelembe veszi ezt a hiányosságot, és egy argumentumot vesz fel a kapott karakterlánc korlátozására. (Ezért nincs snwprintf függvény ).

Példa a sprintf veszélyes hívására :

charbuffer [65536]; char* név = get_user_name_from_keyboard(); sprintf(puffer, "Felhasználónév:%s", név);

A fenti kód implicit módon feltételezi, hogy a felhasználó nem fog 65 ezer karaktert beírni a billentyűzeten, és a puffernek "elég kell lennie". De a felhasználó átirányíthatja a bevitelt egy másik programból, vagy még mindig beírhat több mint 65 000 karaktert. Ebben az esetben a memóriaterületek megsérülnek, és a program viselkedése kiszámíthatatlanná válik.

Használati nehézségek

A típusellenőrzés hiánya

A printf család funkciói C adattípust használnak . Az ilyen típusok mérete és aránya platformonként változhat. Például 64 bites platformokon a választott modelltől ( LP64 , LLP64 vagy ILP64 ) függően az int és long típusok mérete eltérő lehet. Ha a programozó "majdnem helyes"-re állítja a formátum karakterláncot, a kód az egyik platformon működik, a másikon pedig rossz eredményt ad (egyes esetekben adatsérüléshez vezethet).

Például a kód printf( "text address: 0x%X", "text line" );megfelelően működik egy 32 bites platformon ( ptrdiff_t mérete és int mérete 32 bit) és egy 64 bites IPL64 modellen (ahol a ptrdiff_t és az int mérete 64 bit), de 64 bites esetén helytelen eredményt ad. -bites platform egy LP64 vagy LLP64 modellben, ahol a ptrdiff_t mérete 64 bit, az int mérete pedig 32 bit. [22]

Az Oracle Java - ban dinamikus azonosítással burkolt típusokprintf használatosak egy függvény analógjában , [6] az Embarcadero Delphiben  - egy köztes réteg , [23] a különböző megvalósításokban C ++ -ban [24]  - műveletek túlterhelése , C + -ban + 20  - változó sablonok. Ráadásul a formátumok ( , stb.) nem adják meg az argumentum típusát, hanem csak a kimeneti formátumot, így az argumentum típusának megváltoztatása vészhelyzetet okozhat, vagy megtörheti a magas szintű logikát (pl. a táblázat elrendezése) - de nem rontja el a memóriát. array of const%d%f

A szabványosítás hiánya

A problémát súlyosbítja a formátum karakterláncainak elégtelen szabványosítása a különböző fordítókban: például a Microsoft-könyvtárak korai verziói nem támogatták "%lld"(meg kellett adnia "%I64d"). A Microsoft és a GNU között továbbra is létezik típus szerinti felosztás size_t: %Iuaz előbbi és %zuaz utóbbi. A GNU C nem követeli meg a swprintfmaximális karakterlánchosszt egy függvényben (írnod ​​kell snwprintf).

Az argumentumok átrendezésének képtelensége

A családfüggvények kényelmesek printfa szoftverhonosításhoz«You hit %s instead of %s.» : például egyszerűbb lefordítani, mint a karakterlánc-részletek «You hit »és « instead of »a «.». De itt is van egy probléma: lehetetlen a helyettesített karakterláncokat olyan helyekre átrendezni, hogy a következőt kapjuk: «Вы попали не в <2>, а в <1>.».

Az Oracle Java -ban és az Embarcadero Delphibenprintf használt kiterjesztések továbbra is lehetővé teszik az argumentumok átrendezését.

printf segédprogram

A POSIX szabványon belül le van írva a printf segédprogram , amely a printf függvényhez hasonlóan formázza az argumentumokat a megfelelő minta szerint .

A segédprogram a következő hívásformátummal rendelkezik: , where printf format [argument …]

  • A format  egy formátum karakterlánc, amely szintaxisában hasonló a printf függvény formázási karakterláncához .
  • Az argumentum  az argumentumok listája (0 vagy több) karakterlánc formában.

Megvalósítási példák

1. példa C (programozási nyelv)

#include <stdio.h> #include <locale.h> #define PI 3.141593 int main () { setlocale ( LC_ALL , "RUS" ); int szám = 7 ; float pite = 12,75 ; belső költség = 7800 ; printf ( "%d versenyző megevett %f cseresznyés pitét. \n " , szám , piték ); printf ( "A pi értéke %f \n " , PI ); printf ( "Viszlát! A művészeted túl sokba kerül (%c%d) \n " , '$' , 2 * költség ); return 0 ; }

2. példa C (programozási nyelv)

#include <stdio.h> #define OLDALOK 959 int main () { printf ( "*%d* \n " , PAGES ); printf ( "*%2d* \n " , PAGES ); printf ( "*%10d* \n " , PAGES ); printf ( "*%-10d* \n " , PAGES ); return 0 ; } /* Eredmény: *959* *959* * 959* *959 * */

3. példa C (programozási nyelv)

#include <stdio.h> #define BLURB "Hiteles utánzat!" int main () { const dupla BÉRLET = 3852,99 ; printf ( "*%8f* \n " , RENT ); printf ( "*%e* \n " , RENT ); printf ( "*%4.2f* \n " , BÉRLET ); printf ( "*%3.1f* \n " , BÉRLET ); printf ( "*%10.3f* \n " , BÉRLET ); printf ( "*%10.3E* \n " , BÉRLET ); printf ( "*%+4.2f* \n " , BÉRLET ); printf ( "%x %X %#x \n " , 31 , 31 , 31 ); printf ( "**%d**% d% d ** \n " , 42 , 42 , -42 ); printf ( "**%5d**%5.3d**%05d**%05.3d** \n " , 6 , 6 , 6 , 6 ); printf ( " \n " ); printf ( "[%2s] \n " , BLURB ); printf ( "[%24s] \n " , BLURB ); printf ( "[%24.5s] \n " , BLURB ); printf ( "[%-24.5s] \n " , BLURB ); return 0 ; } /* eredmény *3852.990000* *3.852990e+03* *3852.99* *3853.0* * 3852.990* * 3.853E+03* *+3852.99* 1f 1F 0x1f ** 0 ** 2-42 ** 0 ** 2-42 ** **00006** 006** [Hiteles utánzat!] [Hiteles utánzat!] [Authe] [Authe ] */

Linkek

  1. A BCPL nyelv rövid leírása . Letöltve: 2006. december 16. Az eredetiből archiválva : 2006. december 9..
  2. B Nyelvi kalauz archiválva : 2006. július 6.
  3. ↑ A sprintf függvény leírása a Perl dokumentációjában . Letöltve: 2007. január 12. Az eredetiből archiválva : 2007. január 14..
  4. A Python karakterlánc-típusok formázási operátorának leírása Archiválva : 2006. november 9.
  5. ↑ A PHP printf függvényének leírása . Letöltve: 2006. október 23. Az eredetiből archiválva : 2006. november 6..
  6. 1 2 A java.io.PrintStream.printf() függvény leírása a Java 1.5-ben . Letöltve: 2007. január 12. Az eredetiből archiválva : 2007. január 13..
  7. ↑ A printf függvény leírása a Ruby dokumentációban . Letöltve: 2006. december 3. Az eredetiből archiválva : 2006. december 5..
  8. ↑ A string.format függvény leírása a Lua dokumentációjában . Hozzáférés dátuma: 2010. január 14. Az eredetiből archiválva : 2013. november 15.
  9. ↑ A formátum funkció leírása a TCL dokumentációban . Letöltve: 2008. április 14. Az eredetiből archiválva : 2007. július 4..
  10. ↑ A printf karakterlánc-mintájának leírása a GNU Octave dokumentációban . Letöltve: 2006. december 3. Az eredetiből archiválva : 2006. október 27..
  11. ↑ A printf leírása a Maple dokumentációjában{{subst:AI}}
  12. R. Fourer, D. M. Gay és B. W. Kernighan. AMPL: A Modeling Language for Mathematical Programming, 2. kiadás Pacific Grove, CA: Brooks/Cole--Thomson Learning, 2003.
  13. GNU Emacs Lisp Reference Manual, Formatting Strings Archiválva : 2007. szeptember 27. a Wayback Machine -nél
  14. ↑ A Printf modul leírása az OCaml dokumentációban . Letöltve: 2007. január 12. Az eredetiből archiválva : 2007. január 13..
  15. ↑ A Printf modul leírása a Haskell dokumentációban . Letöltve: 2015. június 23. Az eredetiből archiválva : 2015. június 23.
  16. std::println! - Rozsda . doc.rust-lang.org. Letöltve: 2016. július 24. Az eredetiből archiválva : 2016. augusztus 18..
  17. formátum . www.freepascal.org. Letöltve: 2016. december 7. Az eredetiből archiválva : 2016. november 24..
  18. fmt - The Go programozási nyelv . golang.org. Letöltve: 2020. március 25. Az eredetiből archiválva : 2020. április 4.
  19. §7.19.6.1 ISO/IEC 9899:TC2
  20. § 7.11.1.1 ISO/IEC 9899:TC2, LC_NUMERIC határozza meg különösen a decimális elválasztó ábrázolási formáját.
  21. Printf Vulnerability Description, Robert C. Seacord: Biztonságos kódolás C és C++ nyelven. Addison Wesley, 2005. szeptember. ISBN 0-321-33572-4
  22. Az alkalmazások 32 bites architektúráról 64 bites architektúrára történő portolási problémáinak leírása . Letöltve: 2006. december 14. Az eredetiből archiválva : 2007. március 8..
  23. System.SysUtils.Format archiválva : 2013. január 11. a Wayback Machine -nél 
  24. Például a boost::formatdokumentáció archiválva : 2013. március 26. a Wayback Machine -nél 

Források

  • printf , fprintf , snprintf , vfprintf , vprintf , vsnprintf , vsprintf az ISO/IEC 9899:TC2 (ISO C) szabványban [3]
  • printf , fprintf , sprintf , snprintf a Single Unix szabványban [4]
  • vprintf , vfprintf , vsprintf , vsnprintf a POSIX szabványban [5]
  • wprintf , swprintf , wprintf a POSIX szabványban [6]
  • vfwprintf , vswprintf , vwprintf a POSIX szabványban [7]
  • wsprintf az MSDN -n [8]
  • wvnsprintf az MSDN-n [9]
  • wnsprintf az MSDN-n [10]
  • wvsprintf az MSDN-n [11]
  • wnsprintf az MSDN-n [12]
  • asprintf , vasprintf a man -oldalakban Linuxon [13] , a libc dokumentációban [14]
  • A formátum karakterlánc szintaxisának leírását lásd a libc kézikönyvben [15] .
  • A formátum karakterlánc leírása a Microsoft Visual Studio 2005 dokumentációjában [16]
  • A register_printf_function leírása [17] , [18]
  • Programozási nyelv C. Előadások és gyakorlatok. Szerző: Stephen Prata. ISBN 978-5-8459-1950-2 , 978-0-321-92842-9; 2015

Lásd még