我围绕创建一个包装函数strtol()的int16_t,和我碰到一个问题,跑了:如何处理输入如0x?也就是说,它是有效的数字0,后跟非数字x,还是无效,因为没有任何内容0x?
tl; dr结果:Windows 0x完全拒绝,如后一种情况所述,但Debian将其视为数字0,后跟非数字字符x,如前一种情况所述.
实施测试1
为了进一步比较的目的,我包含sscanf()了一个格式规范" %li",它应该strtol()与之一样base==0.令人惊讶的是,我最终得到了两个不同的结果.
码:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
const char *foo = " 0x";
char *remainder;
long n;
int base = 0;
n = strtol(foo, &remainder, base);
printf("strtol(): ");
if (*remainder == 'x')
printf("OK\n");
else {
printf("NOMATCH\n");
printf(" Remaining -- %s\n", remainder);
printf(" errno: %s (%d)\n", strerror(errno), errno);
}
errno = 0;
base = sscanf(foo, " %li", &n);
printf("sscanf(): ");
if (base == 1)
printf("OK\n");
else {
printf("NOMATCH\n");
printf(" Returned: %s\n", base==0 ? "0" : "EOF");
printf(" errno: %s (%d)\n", strerror(errno), errno);
}
}
Run Code Online (Sandbox Code Playgroud)
Debian结果:
strtol(): OK
sscanf(): OK
Run Code Online (Sandbox Code Playgroud)
Windows结果:
strtol(): NOMATCH
Remaining -- 0x
errno: No error (0)
sscanf(): NOMATCH
Returned: 0
errno: No error (0)
Run Code Online (Sandbox Code Playgroud)
在任何情况下都没有错误,但结果不同.初始化base为16而不是0根本没有任何区别,也没有删除测试字符串中的前导空格.
老实说,我得到了Debian上的结果:0被解析为一个有效值(无论base是0还是16),并remainder设置为x在看到后面没有有效的十六进制值之后指向x(如果有的话,那0x将是跳过base是0还是16).
所以现在我对这种情况下的正确行为感到困惑.这些行为中的任何一种都违反了C标准吗?我对标准相关部分的解释是Debian是正确的,但我真的不确定.
1 Cygwin展示了Windows行为的情况strtol()和Debian的行为,sscanf()对于那些感兴趣的人.由于行为是%li应该匹配strtol()的base==0,我认为这是一个错误并忽略了它的结果.
C11的7.22.1.4中的规范:
如果base的值为零,则主题序列的预期形式是整数常量的形式,如6.4.4.1中所述,
主题序列被定义为输入字符串的最长初始子序列,从第一个非空白字符开始,即预期形式
如6.4.4.1中所述,0是一个整数常量,但0x不是.因此,主题序列适用0于您的输入案例.
所以正确的行为是返回0,endptr应该留下指向x.
| 归档时间: |
|
| 查看次数: |
291 次 |
| 最近记录: |