sscanf处理最大无符号整数值的方式与赋值不同

sscanf处理最大无符号整数值的方式与赋值不同,c,scanf,integer-overflow,twos-complement,C,Scanf,Integer Overflow,Twos Complement,考虑以下代码: main() { int assigned = 4294967295; // Max unsigned integer value on 32-bits arch char input[] = "4294967295"; int sscanned; unsigned int result = sscanf(input, "%d", &sscanned); printf ("scanned %u elements : %d\n

考虑以下代码:

main()
{
  int assigned = 4294967295;     // Max unsigned integer value on 32-bits arch

  char input[] = "4294967295";
  int sscanned;


  unsigned int result = sscanf(input, "%d", &sscanned);
  printf ("scanned %u elements : %d\n
          "Assigned j = %d\n", 
          result, sscanned, assigned);

  return 0;
}
当为32位arch编译时(使用编译命令:
gcc-Wall-Wextra-std=c11-pedantic-m32 test\u sscanf.c-o test\u sscanf32
),它会发出一个预期的警告:“从'long long int'转换为'int'时溢出将值从'4294967295'更改为'-1'[-Woverflow]”

现在看到结果:

> ./test_sscanf32 
scanned 1 elements : 2147483647
Assigned j = -1
虽然分配的
值已通过2的补码表示法(-1=-2^31+2^30+…+2^0)正确地转换为最大负符号整数值,另一方面,
扫描的
值显然已取消其MSB,这导致它收缩到值2147483647=2^31-1

因此,我的问题是:在n位机器上处理最大n位整数值时(知道在64位arch上,同样的行为也会发生),有什么理由证明这样的差异
程序员是否有权期望
sscanf
在给定的体系结构上以赋值的方式处理值

scanf
调用使用错误的格式说明符,因此结果不一定有意义

例如,在我的机器上运行相同的代码会得到以下结果:

scanned 1 elements : -1
Assigned j = -1

因此,使用
%u
而不是
%d

scanf
调用使用错误的格式说明符,这样结果就没有意义了

例如,在我的机器上运行相同的代码会得到以下结果:

scanned 1 elements : -1
Assigned j = -1

因此,使用
%u
而不是
%d

通过强制转换或赋值将整数值转换为
int
,当值不可由
int
表示,但可由某个支持的类型以更大范围表示时,将在
int
中生成实现定义的值()。现在几乎所有的实现都定义了这种转换,
intx=UINT\u MAX将x设置为−1.我所知道的唯一例外是Unisys(née Burroughs)大型机,它仍然使用负数的补码表示

相比之下,所有的
scanf
函数在读取一个数字时都有未定义的行为,该数字超出了该数字将被写入的变量类型的可表示范围()。这意味着,你不仅不能指望它做与整数转换相同的事情,你也不能指望它做任何有建设性的事情,事实上,编译器有权生成让恶魔从你鼻子里飞出来的机器代码


我认为7.21.62P10是标准中的一个缺陷,但由于我认为<代码> SCANF家庭无论如何都不适合(这只是其中的一个问题),所以我不必麻烦使用Debug <代码> STRTO */COD>函数。它们具有定义良好且有文档记录的溢出行为。

通过强制转换或赋值将整数值转换为
int
,当值不可由
int
表示,但可由某个范围更大的支持类型表示时,将在
int
()中生成实现定义的值。现在几乎所有的实现都定义了这种转换,
intx=UINT\u MAX将x设置为−1.我所知道的唯一例外是Unisys(née Burroughs)大型机,它仍然使用负数的补码表示

相比之下,所有的
scanf
函数在读取一个数字时都有未定义的行为,该数字超出了该数字将被写入的变量类型的可表示范围()。这意味着,你不仅不能指望它做与整数转换相同的事情,你也不能指望它做任何有建设性的事情,事实上,编译器有权生成让恶魔从你鼻子里飞出来的机器代码


我认为7.21.62P10是标准中的一个缺陷,但由于我认为<代码> SCANF家庭无论如何都不适合(这只是其中的一个问题),所以我不必麻烦使用Debug <代码> STRTO */COD>函数。它们具有定义良好且有文档记录的溢出行为。

使用
%u
读取未签名的int。@wildplasser我知道这一点。但这不是我的问题!我的问题涉及到为什么
sscanf
通过舍弃有符号最大整数值的MSB来处理有符号最大整数值,而赋值只是将其转换为2的补码;扫描由库例程完成。他们可能使用不同的算法从ascii字符中导出值。正如wildplasser所说,使用%u读取未签名的;否则,不会定义结果…例如,编译器本身为64位并截断值,但运行时库例程为32位并溢出。“…为什么sscanf通过丢弃其MSB来处理有符号最大整数值”。事实并非如此。尝试
charinput[]=“4294967290”(最后一位数字0不是5)。我怀疑结果仍然是
2147483647
。查看
strtol()
以了解细节。使用
%u
读取未签名的int。@wildplasser我知道这一点。但这不是我的问题!我的问题涉及到为什么
sscanf
通过舍弃有符号最大整数值的MSB来处理有符号最大整数值,而赋值只是将其转换为2的补码;扫描由库例程完成。他们可能使用不同的算法从ascii字符中导出值。正如wildplasser所说,使用%u读取未签名的;否则不会定义结果…例如,编译器本身为64位并截断值,但运行时库例程为32位并溢出。“。。