如何将字符串可移植地转换为不常见的整数类型?
一些背景:例如,如果我想使用 scanf()
将字符串转换为标准整数类型,例如 uint16_t
,我会使用 来自
,如下所示:
的 SCNu16
#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);
但是像 pid_t
这样更不常见的整数类型没有任何这样的东西;
仅支持普通整数类型。 要以另一种方式转换,以可移植 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
的最大值或最小值。
Some background: If I wanted to use for, for instance, scanf()
to convert a string into a standard integer type, like uint16_t
, I’d use SCNu16
from <inttypes.h>
, like this:
#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);
But a more uncommon integer type like pid_t
does not have any such thing; only the normal integer types are supported by <inttypes.h>
. To convert the other way, to portably printf()
a pid_t
, I can cast it to intmax_t
and use PRIdMAX
, like this:
#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);
However, there does not seem to be a way to portably scanf()
into a pid_t
. So this is my question: How to do this portably?
#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! /*
I thought of scanf()
ing to an intmax_t
and then checking that the value is within pid_t
’s limits before casting to pid_t
, but there does not seem to be a way to get the maximum or minimum values for pid_t
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
有一种强大且可移植的解决方案,即使用 strtoimax() 并检查溢出。
也就是说,我解析
intmax_t
,检查strtoimax()
中的错误,然后查看它是否“适合”pid_t
通过转换它并将其与原始intmax_t
值进行比较。不可能使用
scanf()
,因为(正如我在评论中所说)scanf()
不会检测溢出。 但我错误地指出,与strtoll()
相关的函数都没有采用intmax_t
;strtoimax()
可以!除非您知道整数类型的大小(在本例中为
pid_t
),否则使用strtoimax()
之外的任何内容都不起作用。There is one robust and portable solution, which is to use
strtoimax()
and check for overflows.That is, I parse an
intmax_t
, check for an error fromstrtoimax()
, and then also see if it "fits" in apid_t
by casting it and comparing it to the originalintmax_t
value.It is not possible to use
scanf()
, because, (as I said in a comment)scanf()
will not detect overflows. But I was wrong in saying that none of thestrtoll()
-related functions takes anintmax_t
;strtoimax()
does!It also will not work to use anything else than
strtoimax()
unless you know the size of your integer type (pid_t
, in this case).这完全取决于您想要的便携性。 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 书店 找到的。
我所看到的只是它必须是有符号整数类型。 显然,所有有效的有符号整数值都适合 intmax_t。 我在
或
中找不到任何指示 PID_T_MAX 或 PID_T_MIN 或其他此类值的信息(但我只有这个晚上可以访问它,所以它可能隐藏在我没有寻找它的地方)。 OTOH,我坚持我原来的评论 - 我相信 32 位值在实用上是足够的,无论如何我都会使用long
,这在 8 位机器上将是 64 位。 我认为可能发生的最糟糕的事情是“适当特权”的进程读取了太大的值,并由于类型不匹配而向错误的进程发送了信号。 我不相信我会为此担心。...哦!...下的 p400
It depends on exactly how portable you want to be. POSIX says that
pid_t
is a signed integer type used to store process IDs and process group IDs. In practice, you could assume with safety thatlong
is big enough. Failing that, yourintmax_t
must be big enough (so it will accept any validpid_t
); the trouble is, that type could accept values that are not legitimate inpid_t
. You're stuck between a rock and a hard place.I would use
long
and not worry very much about it except for an obscure comment somewhere that a software archaeologist of 100 years hence will find and observe gives a reason why the 256-bit CPU is creaking to a halt when handed a 512-bit value as apid_t
.POSIX 1003.1-2008 is now available on the web (all 3872 pages of it, in PDF and HTML). You have to register (free). I got to it from the Open Group Bookstore.
All that I see there is that it must be a signed integer type. Clearly, all valid signed integer values fit into
intmax_t
. I cannot find any information in<inttypes.h>
or<unistd.h>
that indicates PID_T_MAX or PID_T_MIN or other such values (but I've only just this evening got access to it, so it could be hidden where I haven't looked for it). OTOH, I stand by my original comment - I believe that 32-bit values are pragmatically adequate, and I would uselong
anyway, which would be 64-bit on 8-bit machines. I suppose that roughly the worst thing that could happen is that an 'appropriately privileged' process read a value that was too large, and sent a signal to the wrong process because of a mismatch of types. I'm not convinced I'd be worried about that....oooh!...p400 under
<sys/types.h>
如果您确实担心,可以使用
_assert(sizeof(pid_t) <= long)
或您为“%”内容选择的任何类型。正如这个答案中所解释的< /a>,规范说
signed int
。 如果 'int' 改变,你的 '%u' 根据定义也会随之改变。If you are really concerned you can
_assert(sizeof(pid_t) <= long)
or whatever type you choose for your '%' stuff.As explained in this answer, the spec says
signed int
. If 'int' changes, your '%u' by definition changes with it.