一些背景:如果我想用于,例如, 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()
到了 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年的软件考古学家会发现并观察到的一个模糊的评论,给出了为什么256位CPU在将512位值作为 pid_t
。
POSIX 1003.1-2008 现在可在网上获得(所有3872页,PDF和HTML)。你必须注册(免费)。我从中得到了它 Open Group Bookstore。
我所看到的只是它必须是有符号整数类型。显然,所有有效的有符号整数值都适合 intmax_t
。我找不到任何信息 <inttypes.h>
要么 <unistd.h>
这表示PID_T_MAX或PID_T_MIN或其他此类值(但我今晚只是访问它,所以它可能隐藏在我没有找到的地方)。 OTOH,我支持我的原始评论 - 我相信32位值是实用的,我会用 long
无论如何,这在8位机器上是64位的。我认为可能发生的最糟糕的事情是“适当特权”进程读取的值太大,并且由于类型不匹配而向错误的进程发送信号。我不相信我会担心这一点。
......哦!... p400下 <sys/types.h>
实现应支持一个或多个宽度的编程环境
blksize_t,pid_t,size_t,ssize_t和suseconds_t的值不大于long类型的宽度。
有一个强大的便携式解决方案,即可使用 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年的软件考古学家会发现并观察到的一个模糊的评论,给出了为什么256位CPU在将512位值作为 pid_t
。
POSIX 1003.1-2008 现在可在网上获得(所有3872页,PDF和HTML)。你必须注册(免费)。我从中得到了它 Open Group Bookstore。
我所看到的只是它必须是有符号整数类型。显然,所有有效的有符号整数值都适合 intmax_t
。我找不到任何信息 <inttypes.h>
要么 <unistd.h>
这表示PID_T_MAX或PID_T_MIN或其他此类值(但我今晚只是访问它,所以它可能隐藏在我没有找到的地方)。 OTOH,我支持我的原始评论 - 我相信32位值是实用的,我会用 long
无论如何,这在8位机器上是64位的。我认为可能发生的最糟糕的事情是“适当特权”进程读取的值太大,并且由于类型不匹配而向错误的进程发送信号。我不相信我会担心这一点。
......哦!... p400下 <sys/types.h>
实现应支持一个或多个宽度的编程环境
blksize_t,pid_t,size_t,ssize_t和suseconds_t的值不大于long类型的宽度。
如果你真的担心,你可以 _assert(sizeof(pid_t) <= long)
或者你为'%'的东西选择的任何类型。
如中所述 这个答案,规范说 signed int
。如果'int'发生变化,你的'%u'按定义会随之改变。