扫描数据多于预定义值的数字
Scanning a number having more data than predefined value
#include<stdio.h>
main()
{
unsigned int num;
printf("enter the number:\n");
scanf("%u",&num);//4294967299 if i'm scanning more than 4G its not scanning
printf("after scanning num=%u\n",num);// 4294967295 why its giving same 4G
/* unsigned char ch;
printf("enter the character:\n");
scanf("%d",&ch);// if i/p=257 so its follow circulation
printf("after scanning ch=%d\n",ch);// 1 its okk why not in int ..
*/
}
为什么通过scanf()
扫描输入时循环不跟随,为什么在char
的情况下循环?
来自 this scanf
(and family) reference "%u"
格式:
The format of the number is the same as expected by strtoul()
with the value 0
for the base argument (base is determined by the first characters parsed)
然后我们转到 strtoul
函数,并阅读 returned 值:
Integer value corresponding to the contents of str on success. If the converted value falls out of range of corresponding return type, range error occurs and ULONG_MAX
or ULLONG_MAX
is returned. If no conversion can be performed, 0
is returned.
由此可见,如果scanf
"%u"
格式输入的值过大,那么结果会ULONG_MAX
转换为unsigned int
。 但是 结果在 sizeof(unsigned long) > sizeof(unsigned int)
的系统上会有所不同。有关这方面的信息,请参阅下文。
需要注意的是,在64位unsigned long
和32位unsigned int
的平台上,unsigned long
范围内有效的值不会被转换为例如UINT_MAX
,而是使用模运算 as detailed here.
进行转换
让我们取 4294967299
这样的值。它对于 32 位 unsigned int
来说太大了,但是对于 64 位 unsigned long
来说却非常适合。因此对 strtoul
的调用不会 return ULONG_MAX
,而是 4294967299
的值。使用标准转换规则(链接到上面),这将导致 unsigned int
值为 3
。
C11 标准草案 n1570 7.21.6.2 说如下
[...] the input item [...] is converted to a type appropriate to the conversion specifier. If the input item is not a matching sequence, the execution of the directive fails: this condition is a matching failure. Unless assignment suppression was indicated by a *
, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result. If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
这里"conversion"这个词是用来进行字符串=>结果数据类型转换的,不能理解为整数转换。由于转换为十进制整数的字符串 "4294967299"
在 32 位宽的 unsigned int
类型的对象中不可表示,因此标准的阅读表明行为未定义,即
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
因此,您的问题的答案是 C 标准没有说明这种情况下的行为,您看到的行为是您的编译器和 C 库实现所展示的行为,并且不可移植;在其他平台上,可能的行为可能包括:
ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
#include<stdio.h>
main()
{
unsigned int num;
printf("enter the number:\n");
scanf("%u",&num);//4294967299 if i'm scanning more than 4G its not scanning
printf("after scanning num=%u\n",num);// 4294967295 why its giving same 4G
/* unsigned char ch;
printf("enter the character:\n");
scanf("%d",&ch);// if i/p=257 so its follow circulation
printf("after scanning ch=%d\n",ch);// 1 its okk why not in int ..
*/
}
为什么通过scanf()
扫描输入时循环不跟随,为什么在char
的情况下循环?
来自 this scanf
(and family) reference "%u"
格式:
The format of the number is the same as expected by
strtoul()
with the value0
for the base argument (base is determined by the first characters parsed)
然后我们转到 strtoul
函数,并阅读 returned 值:
Integer value corresponding to the contents of str on success. If the converted value falls out of range of corresponding return type, range error occurs and
ULONG_MAX
orULLONG_MAX
is returned. If no conversion can be performed,0
is returned.
由此可见,如果scanf
"%u"
格式输入的值过大,那么结果会ULONG_MAX
转换为unsigned int
。 但是 结果在 sizeof(unsigned long) > sizeof(unsigned int)
的系统上会有所不同。有关这方面的信息,请参阅下文。
需要注意的是,在64位unsigned long
和32位unsigned int
的平台上,unsigned long
范围内有效的值不会被转换为例如UINT_MAX
,而是使用模运算 as detailed here.
让我们取 4294967299
这样的值。它对于 32 位 unsigned int
来说太大了,但是对于 64 位 unsigned long
来说却非常适合。因此对 strtoul
的调用不会 return ULONG_MAX
,而是 4294967299
的值。使用标准转换规则(链接到上面),这将导致 unsigned int
值为 3
。
C11 标准草案 n1570 7.21.6.2 说如下
[...] the input item [...] is converted to a type appropriate to the conversion specifier. If the input item is not a matching sequence, the execution of the directive fails: this condition is a matching failure. Unless assignment suppression was indicated by a
*
, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result. If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
这里"conversion"这个词是用来进行字符串=>结果数据类型转换的,不能理解为整数转换。由于转换为十进制整数的字符串 "4294967299"
在 32 位宽的 unsigned int
类型的对象中不可表示,因此标准的阅读表明行为未定义,即
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
因此,您的问题的答案是 C 标准没有说明这种情况下的行为,您看到的行为是您的编译器和 C 库实现所展示的行为,并且不可移植;在其他平台上,可能的行为可能包括:
ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).