Wie man portably einen String in einen ungewöhnlichen Integer-Typen umwandeln?
Frage
Einige Hintergrundinformationen: Wenn ich zum Beispiel verwenden wollte, scanf()
einen String in einem Standard-Integer-Typ zu konvertieren, wie uint16_t
, ich SCNu16
von <inttypes.h>
verwenden würde, wie folgt aus:
#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);
Aber ein seltener Integer-Typ wie pid_t
hat keine solche Sache; nur die normalen Integer-Typen werden durch <inttypes.h>
unterstützt. Um die andere Art und Weise zu konvertieren, zu portably eine printf()
pid_t
, ich kann es zu gieße intmax_t
und verwenden PRIdMAX
, wie folgt aus:
#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);
Doch es scheint keinen Weg, um portabel in eine scanf()
pid_t
. Das ist also meine Frage: Wie diese portably tun
#include <stdio.h>
#include <sys/types.h>
pid_t x;
char *xs = 17;
sscanf(xs, "%u", &x); /* Not portable! pid_t might not be int! /*
Ich dachte an scanf()
ing zu einem intmax_t
und dann prüfen, ob der Wert innerhalb pid_t
der Grenzen vor dem pid_t
Gießen, aber es scheint nicht ein Weg zu sein, um die Maximal- oder Minimalwerte für pid_t
zu erhalten.
Lösung
Es ist eine robuste und tragbare Lösung, die strtoimax()
zu verwenden ist und prüfen, ob überläuft.
Das heißt, ich eine intmax_t
analysieren, überprüfen Sie für einen Fehler von strtoimax()
, und dann sehen, auch wenn es „passt“ in einem pid_t
durch Gießen und es auf den ursprünglichen intmax_t
Wert verglichen wird.
#include <inttypes.h>
#include <stdio.h>
#include <iso646.h>
#include <sys/types.h>
char *xs = "17"; /* The string to convert */
intmax_t xmax;
char *tmp;
pid_t x; /* Target variable */
errno = 0;
xmax = strtoimax(xs, &tmp, 10);
if(errno != 0 or tmp == xs or *tmp != '\0'
or xmax != (pid_t)xmax){
fprintf(stderr, "Bad PID!\n");
} else {
x = (pid_t)xmax;
...
}
Es ist nicht möglich scanf()
zu verwenden, da (wie ich in einem Kommentar sagte) scanf()
nicht erkennen, überläuft . Aber ich war falsch zu sagen, dass keine der strtoll()
bezogenen Funktionen eine intmax_t
nimmt; strtoimax()
tut!
Es wird auch nicht funktionieren, irgendetwas anderes als strtoimax()
zu verwenden, wenn Sie die Größe Ihrer Integer-Typ kennen (pid_t
, in diesem Fall).
Andere Tipps
Es hängt davon ab, wie genau tragbar Sie sein möchten. POSIX sagt, dass pid_t
ein Integer-Typ zum Speichern von Prozess-IDs und Prozessgruppe IDs verwendet signiert ist. In der Praxis könnte man mit Sicherheit davon ausgehen, dass long
groß genug ist. Gelingt das nicht, muss Ihr intmax_t
groß genug sein, um (so wird es jede gültige pid_t
akzeptieren); Das Problem ist, könnte diese Art Werte annehmen, die nicht legitim in pid_t
sind. Sie sind zwischen einem Felsen und einem harten Platz fest.
Ich würde verwenden long
und nicht sehr viel Sorgen um es mit Ausnahme eines obskuren Kommentar irgendwo, dass ein Software-Archäologe von 100 Jahren wird daher finden und beobachten gibt einen Grund, warum die 256-Bit-CPU zum Stillstand Knarren, wenn ein 512 übergeben -Bit-Wert als pid_t
.
POSIX 1.003,1-2.008 ist jetzt im Internet verfügbar (alle 3872 Seiten davon, in PDF und HTML). Sie müssen (kostenlos) registrieren. Ich habe es aus der Open Group Buchhandlung .
Alles, was ich sehe, es ist, dass es ein signierter Integer-Typ sein muss. Natürlich werden alle gültigen signierten Integer-Werte passen in intmax_t
. Ich kann keine Informationen in <inttypes.h>
oder <unistd.h>
finden, die PID_T_MAX oder PID_T_MIN oder andere solche Werte gibt (aber ich habe nur gerade an diesem Abend bekam Zugang zu ihm, so könnte es versteckt werden, wo ich nicht für sie ausgesehen haben). OTOH, wird ich von meinem ursprünglichen Kommentar stehen - ich glaube, dass 32-Bit-Werte pragmatisch angemessen sind, und ich würde auf jeden Fall verwenden long
, die 64-Bit auf 8-Bit-Maschinen wäre. Ich nehme an, dass etwa das Schlimmste, was passieren könnte, ist, dass ein ‚in geeigneter Weise privilegiert‘ -Prozess Wert gelesen, der zu groß war, und schickte wegen einer Nichtübereinstimmung von Typen ein Signal an den falschen Prozess. Ich bin nicht überzeugt, was ich darüber besorgt sein würde.
... oooh! ... p400 unter <sys/types.h>
Die Umsetzung soll eine oder mehr Programmierumgebungen unterstützen, in denen die Breiten von blksize_t, pid_t, size_t, ssize_t und suseconds_t sind nicht größer als die Breite des Typs lang.
Wenn Sie wirklich besorgt sind, können Sie _assert(sizeof(pid_t) <= long)
oder welcher Art auch immer Sie für Ihre ‚%‘ Sachen wählen.
Wie in erklärt diese Antwort , sagt der spec signed int
. Wenn 'int' ändert, Ihr '% u' definitions Änderungen mit sich.