tomografia - manual de programacion android pdf
¿Cómo convertir una cadena en un tipo entero poco común? (3)
Algunos antecedentes: si quisiera usar, por ejemplo, scanf()
para convertir una cadena en un tipo de entero estándar, como uint16_t
, usaría SCNu16
desde <inttypes.h>
, así:
#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);
Pero un tipo entero más infrecuente como pid_t
no tiene tal cosa; solo los tipos enteros normales son compatibles con <inttypes.h>
. Para convertir de la otra manera, a portable printf()
un pid_t
, puedo convertirlo a intmax_t
y usar PRIdMAX
, así:
#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);
Sin embargo, no parece haber una forma de escanear portátilmente scanf()
en un pid_t
. Entonces esta es mi pregunta: ¿cómo hacer esto de forma portátil?
#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! /*
Pensé en scanf()
a un intmax_t
y luego comprobar que el valor está dentro de los límites de pid_t
antes de pid_t
a pid_t
, pero no parece haber una manera de obtener los valores máximos o mínimos para pid_t
.
Depende de qué tan portátil quieras ser. POSIX dice que pid_t
es un tipo de entero con signo utilizado para almacenar ID de proceso e ID de grupo de proceso. En la práctica, se puede asumir con seguridad que el long
es lo suficientemente grande. De lo intmax_t
, su intmax_t
debe ser lo suficientemente grande (por lo que aceptará cualquier pid_t
válido); el problema es que ese tipo podría aceptar valores que no son legítimos en pid_t
. Estás atrapado entre una roca y un lugar duro.
Usaría long
y no me preocuparía mucho, excepto por un oscuro comentario en algún lugar que un arqueólogo de software de 100 años encontrará y observa, da una razón por la cual la CPU de 256 bits se detiene cuando se le entrega un valor de 512 bits como un pid_t
.
POSIX 1003.1-2008 ya está disponible en la web (las 3872 páginas en PDF y HTML). Debes registrarte (gratis) Llegué a él desde la Librería Open Group .
Todo lo que veo allí es que debe ser un tipo entero con signo. Claramente, todos los valores enteros con signo válidos caben en intmax_t
. No puedo encontrar ninguna información en <inttypes.h>
o <unistd.h>
que indique PID_T_MAX o PID_T_MIN u otros valores similares (pero esta noche solo he tenido acceso a él, por lo que podría estar oculto donde no lo he hecho). lo busqué). OTOH, estoy de acuerdo con mi comentario original: creo que los valores de 32 bits son pragmáticamente adecuados, y de todos modos usaría long
, que sería de 64 bits en máquinas de 8 bits. Supongo que aproximadamente lo peor que podría pasar es que un proceso "apropiadamente privilegiado" lea un valor que sea demasiado grande y envíe una señal al proceso incorrecto debido a una falta de coincidencia de tipos. No estoy convencido de que estaría preocupado por eso.
... oooh! ... p400 en <sys/types.h>
La implementación debe admitir uno o más entornos de programación en los cuales los anchos de blksize_t, pid_t, size_t, ssize_t y suseconds_t no son mayores que el ancho de tipo long.
Existe una solución robusta y portátil, que es usar strtoimax()
y verificar si hay desbordamientos.
Es decir, intmax_t
un intmax_t
, intmax_t
si hay un error de strtoimax()
, y luego también veo si "encaja" en un pid_t
fundiéndolo y comparándolo con el valor intmax_t
original.
#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;
...
}
No es posible utilizar scanf()
, porque (como dije en un comentario) scanf()
no detectará desbordamientos . Pero me equivoqué al decir que ninguna de las funciones relacionadas con strtoll()
toma una intmax_t
; strtoimax()
hace!
Tampoco funcionará usar nada más que strtoimax()
menos que sepas el tamaño de tu tipo entero ( pid_t
, en este caso).
Si está realmente preocupado, puede _assert(sizeof(pid_t) <= long)
o el tipo que elija para su elemento ''%''.
Como se explica en esta respuesta , la especificación dice signed int
. Si ''int'' cambia, su ''% u'' por definición cambia con él.