如何将字符串便携转换为一种罕见的整数类型?
题
一些背景资料:如果我想使用的,例如,scanf()
将字符串转换成标准的整数类型,像uint16_t
,我会使用SCNu16
从<inttypes.h>
,像这样的:
#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);
但是,像pid_t
更罕见的整数类型不具有任何这样的东西;只有正常整数类型由<inttypes.h>
支持。以其他方式转换,可移植printf()
一个pid_t
,我可以投它intmax_t
和使用PRIdMAX
,像这样的:
#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);
然而,似乎没有一种方法来便携scanf()
成pid_t
。因此,这是我的问题:怎样便携做到这一点。
#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! /*
我想scanf()
ing到intmax_t
,然后检查该值pid_t
的范围之内铸造pid_t
过,但似乎没有成为一种方式来获得的最高或最低值pid_t
。
解决方案
有一个坚固的和便携的解决方案,这是使用strtoimax()
并检查溢出。
也就是说,我解析intmax_t
,检查来自strtoimax()
一个错误,然后也看它是否通过铸造它并将其与原来的pid_t
值“适合”在intmax_t
。
#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;
...
}
这是不可能使用scanf()
,因为,(如我在注释所述)的 scanf()
不会检测溢出即可。但我说,没有任何的strtoll()
相关的功能需要一个intmax_t
是错误的; strtoimax()
呢!
这也是不行使用别的比strtoimax()
除非你知道你的整数类型的大小(pid_t
,在这种情况下)。
其他提示
这取决于你想究竟如何便携式是。 POSIX说,pid_t
是用于存储进程ID和进程组ID的符号整型。在实践中,你可以安全假定long
足够大。如果做不到这一点,你intmax_t
必须足够大(所以它将接受任何有效的pid_t
);问题是,这种类型的可以接受不在pid_t
合法值。你陷入一个进退两难的境地。
我会用long
并没有很担心关于它除了一个不起眼的注释的地方,100年的软件考古学家因此将发现和观察给出了一个理由递上一张512当256位CPU的吱吱作响停顿位值作为pid_t
。
POSIX 1003.1-2008 是现在可在网络上(所有3872它的网页,PDF和HTML)。你必须注册(免费)。我将其从公开组书店。
所有我看到有,它必须是一个带符号的整数类型。显然,所有有效符号整数融入intmax_t
。我无法找到<inttypes.h>
或<unistd.h>
表示PID_T_MAX或PID_T_MIN或其他此类值的任何信息(但我才刚了今晚访问它,因此它可以被隐藏在那里我没有看过它)。 OTOH,我坚持我原来的注释 - 我相信,32位值是务实足够,我无论如何都会使用long
,这将是64位的8位机。我想这大概可能发生的最糟糕的事情是,一个“适当的权限”的过程中读到过大的值,并发出信号,错误的过程,因为类型不匹配。我不相信我会担心这一点。
......哦!......下<sys/types.h>
P400
的执行应支持一个或多个编程环境,其中,宽度 blksize_t,将为pid_t,为size_t,ssize_t供,和suseconds_t的是不大于型长的宽度大。
如果你真的关心你可以_assert(sizeof(pid_t) <= long)
或您为“%”的东西无论何种类型。
如解释这个答案,规范说signed int
。如果“诠释”的变化,你的定义改变“%u”吧。