Verwenden von ssize_t vs. int

Lesezeit: 5 Minuten

Benutzeravatar von Hyde
Hyde

Code

Ich habe eine Funktion, in die ich schreiben kann eines von vier möglichen Wegen:

    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);   

Und dann wird mit gerufen beide dieser Möglichkeiten für Bibliotheksfunktionen:

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

Fragen

  • Welchen Prototyp soll ich verwenden?
  • Welche Typen soll ich geben written und printed?

Ich möchte den robustesten und standardisiertesten Code haben, während ich immer noch nur einen habe do_or_die Funktion.

Ich verwende in diesem Fall C99, aber wenn die Antwort für C11 anders ist, würde ich das auch für die Zukunft gerne wissen.

  • Seit ssize_t kann durchaus breiter sein als int Sie sollten wahrscheinlich mit dem vierten Prototyp gehen.

    – PaulR

    7. Oktober 2013 um 12:17 Uhr


  • @PaulR Ist das garantiert oder könnte int auch breiter sein als ssize_t?

    Benutzer395760

    7. Oktober 2013 um 12:18 Uhr


  • @delnan: Ich glaube nicht, dass das möglich ist, obwohl sie vielleicht gleich sind.

    – PaulR

    7. Oktober 2013 um 12:19 Uhr

  • @PaulR Nun, ich kann mir eine Architektur vorstellen, bei der int breiter ist: Segmentierter Speicher a la 16-Bit-x86 (also ssize_t ist 16-Bit) mit 32-Bit-Ganzzahlen. Die Frage ist wirklich, ob die relevanten Standards (eine Version von C, und in diesem Fall POSIX) irgendetwas garantieren.

    Benutzer395760

    7. Oktober 2013 um 12:23 Uhr

  • Danke allen für den Einblick! Ich denke, im echten Code werde ich tun int do_or_die(intmax_t retval); und sauber verlassen, wenn es nicht passt, weil der Rückgabewert nicht in einen passt int ist aufgrund bestimmter physikalischer Beschränkungen des Systems rein theoretisch.

    – Hyde

    7. Oktober 2013 um 13:21 Uhr

Benutzeravatar von Fred Foo
Fred Fu

Dafür gibt es im POSIX-Standard keine Garantie sizeof(int) >= sizeof(ssize_t), noch umgekehrt. Typisch ssize_t ist größer als intaber die sichere und portable Option in C99 ist die Verwendung intmax_t stattdessen für das Argument und den Rückgabewert.

Die einzigen Garantien, die Sie bzgl. die Beziehung zwischen int und ssize_t sind:

  • int kann Werte von mindestens dem Bereich speichern [-2^15 … 2^15-1] nach ISO C
  • ssize_t kann Werte von mindestens dem Bereich speichern [-1 … 2^15-1] pro POSIX (vgl _POSIX_SSIZE_MAX).

(Interessanterweise gibt es dafür nicht einmal eine Garantie ssize_t kann die negativen Gegenstücke seines positiven Bereichs speichern. Es ist nicht signiert size_taber ein “Größentyp” mit einem Fehlerwert.)

  • ssize_t ist im C-Standard eigentlich gar nicht spezifiziert. Es ist Teil des POSIX-Standards.

    – Bill Lynch

    7. Oktober 2013 um 12:23 Uhr

  • Der Link für ssize_t erwähnt nur die maximale Größe und nicht mehr, nicht einmal die Signiertheit. Können Sie dafür eine Referenz angeben? Vielen Dank.

    – 2501

    7. Februar 2016 um 11:02 Uhr

  • Das habe ich gerade erst entdeckt int_fast64_t existiert in C++11. Ich bin versucht, es als meinen Standard-Ganzzahltyp zu verwenden “schnellster vorzeichenbehafteter Ganzzahltyp mit einer Breite von mindestens 8, 16, 32 bzw. 64 Bit”. en.cppreference.com/w/cpp/types/integer

    – Aaron McDaid

    7. Juli 2016 um 11:18 Uhr

  • Wie das, was @ 2501 sagte, können Sie bitte mehr Referenzen zum Mindestwert posten, da die von Ihnen gepostete Referenz nichts über das Minimum aussagt.

    – Ravi

    24. März 2017 um 2:53 Uhr


  • @AaronMcDaid Was Sie geschrieben haben, scheint nichts mit dem zu tun zu haben, was hier diskutiert wird. Wie für Ihre Versuchung zu verwenden int_fast64_t, würde ich empfehlen, dies nur zu verwenden, wenn Sie mindestens 64 Bit benötigen, was kein häufiger Anwendungsfall ist. Etwas wie int_fast32_t sollte in den meisten Situationen funktionieren. Es ist die schnellste vorzeichenbehaftete Ganzzahl auf Ihrer Plattform mit mindestens 32 Bit (es können jedoch 64 Bit sein).

    – Benutzer904963

    26. März um 12:16 Uhr

Benutzeravatar von LihO
Liho

Verwenden Sie Typen auf eine Weise:

  • du mischst nicht signed und unsigned Typen zusammen und
  • Sie schneiden keine Werte von größeren Typen ab, während Sie sie in kleineren Typen speichern (Überlauf/Unterlauf)

ssize_t könnte ein Alias ​​für sein intist jedoch kein Standard-C und kann umgebungsspezifisch sein.

Wenn Ihr Programm in einer bestimmten Umgebung ausgeführt wird, prüfen Sie, ob sizeof(ssize_t) <= sizeof(int) und verwenden int. Verwenden Sie andernfalls einen anderen Typ T wo sizeof(T) größer oder gleich als beide ist sizeof(int) und sizeof(ssize_t).

  • ssize_t ist kein Alias ​​für int auf x86-64-Systemen.

    – Fred Foo

    7. Oktober 2013 um 12:29 Uhr

  • @larsmans: Ich habe es umformuliert in “könnte ein Alias ​​für sein int” 🙂

    – Liho

    7. Oktober 2013 um 12:31 Uhr

  • Ich denke, aus praktischen Gründen ssize_t hätte mindestens die gleiche Größe wie ein Zeiger, oder es gäbe eine unvernünftige Begrenzung der maximalen Schreibgröße. Aber ich denke, es gibt keine Garantie dafür, dass die Größe des Zeigers >= Größe von int ist, oder gibt es das?

    – Hyde

    7. Oktober 2013 um 12:32 Uhr


  • @hyde: normalerweise ssize_t ist das signierte Gegenstück von size_taber POSIX garantiert nicht einmal das.

    – Fred Foo

    7. Oktober 2013 um 12:36 Uhr

  • @larsmans Nun, write kehrt zurück ssize_taber dauert size_t Parameter (wie auch malloc), also würde es bei großen Schreibvorgängen haarig werden, wenn der Rückgabewert überlaufen könnte. Das ist auch nicht alles theoretisch, wenn man bedenkt, dass es 32-Bit-Systeme mit 4 GB installiertem Speicher gibt.

    – Hyde

    7. Oktober 2013 um 13:12 Uhr

Sie können jedoch die Datentypen int oder long int verwenden ssize_t ist ein Systemdatentyp, der für die plattformübergreifende Portabilität verwendet werden sollte. Die grundlegenden Typen (z. B. „int“) können bei verschiedenen Implementierungen unterschiedliche Größen haben. Was normalerweise passiert, ist der Systemtyp (in diesem Fall ssize_t) nutzt die Typedef-Funktion von C, sodass die maschinenspezifische Datentypgröße verwendet wird, z typedef signed ssize_t (Dies ist Teil der SUSv3-Standarddatentypen). Es empfiehlt sich, bei der Implementierung jeglicher Art von Programmierung auf Systemebene nach Möglichkeit Systemdatentypen zu verwenden.

Für eine ausführlichere Beschreibung siehe The Linux Programming Interface (Michael Kerrisk)

1396930cookie-checkVerwenden von ssize_t vs. int

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy