Ssize_t vs int gebruiken

Ik heb een functie die ik op éénvan de vier mogelijke manieren kan schrijven:

   int do_or_die(int retval);
    int do_or_die(ssize_t retval);
    ssize_t do_or_die(int retval);   
    ssize_t do_or_die(ssize_t retval);   

En dan wordt het aangeroepen met beidevan deze manieren voor bibliotheekfuncties:

   written = do_or_die(write(...)); // POSIX write returns ssize_t
    printed = do_or_die(printf(...)); // printf returns int

Vragen

  • Welk prototype moet ik gebruiken?
  • Welke soorten moet ik geven aan writtenen printed?

Ik wil de meest robuuste en standaardcode hebben, terwijl ik nog steeds maar één do_or_die-functie heb.

In dit geval gebruik ik C99, maar als het antwoord voor C11 anders is, dan zou ik dat ook graag willen weten voor de toekomst.


Antwoord 1, autoriteit 100%

Er is geen garantie in de POSIX-standaard dat sizeof(int) >= sizeof(ssize_t), noch andersom. Meestal is ssize_tgroter dan int, maar de veilige en draagbare optie in C99 is om in plaats daarvan intmax_tte gebruiken voor het argument en de retourwaarde.

De enige garanties die je hebt tov. de relatie tussen inten ssize_tzijn:

  • intkan waarden opslaan van ten minste het bereik [-2^15 … 2^15-1] per ISO C
  • ssize_tkan waarden van ten minste het bereik [-1 … 2^15-1] per POSIX opslaan (zie _POSIX_SSIZE_MAX).

(Interessant is dat er zelfs geen garantie is dat ssize_tde negatieve tegenhangers van zijn positieve bereik kan opslaan. Het is geen ondertekende size_t, maar een “maattype ” met een foutwaarde.)


Antwoord 2, autoriteit 9%

Gebruik typen op een bepaalde manier:

  • je mengt signeden unsignedtypen niet door elkaar en
  • u kapt geen waarden af van grotere typen terwijl u ze opslaat in kleinere typen (overloop/onderloop)

ssize_tis misschien een alias voor int, maar het is geen standaard C en kan omgevingsspecifiek zijn.

Als uw programma in een specifieke omgeving draait, controleer dan of sizeof(ssize_t) <= sizeof(int)en gebruik int. Gebruik anders een ander type Twaarbij sizeof(T)groter of gelijk is aan zowel sizeof(int)als sizeof(ssize_t).


Antwoord 3

U kunt de gegevenstypen int of long int gebruiken, maar ssize_tis een systeemgegevenstype dat moet worden gebruikt voor platformonafhankelijke portabiliteit. De fundamentele typen (zoals ‘int’) kunnen verschillende groottes hebben bij verschillende implementaties. Wat er meestal gebeurt, is dat het systeemtype (in dit geval ssize_t) gebruikmaakt van de typedef-functie van C, zodat de machinespecifieke grootte van het gegevenstype wordt gebruikt, b.v. typedef signed ssize_t(dit maakt deel uit van SUSv3 standaard datatypes). Het is een goede gewoonte om, waar mogelijk, systeemgegevenstypen te gebruiken bij het implementeren van enige vorm van programmering op systeemniveau.

Raadpleeg voor een meer gedetailleerde beschrijving de Linux-programmeerinterface (Michael Kerrisk)

Other episodes