【问题标题】:Scanning a number having more data than predefined value扫描数据多于预定义值的数字
【发布时间】:2015-09-18 09:20:08
【问题描述】:
#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的情况下循环跟随?

【问题讨论】:

  • @JoachimPileborg 但是他们是unsigned type 所以为什么它会是未指定的行为。
  • 在编译时,如果我的取值超过 range ,请正确评估它的值,但为什么不在运行时?
  • 输入编译器将解析的整数文字是一回事,scanf 函数完全是另一回事。这两者和它们的解析无关。

标签: c scanf


【解决方案1】:

C11 标准草案 n1570 7.21.6.2 说明如下

paragraph 10

[...] 输入项 [...] 被转换为适合转换说明符的类型。如果输入项不是匹配序列,则指令执行失败:此条件为匹配失败。除非* 指示分配抑制,否则转换结果将放置在尚未收到转换结果的格式参数之后的第一个参数所指向的对象中。如果此对象没有合适的类型,或者转换的结果无法在对象中表示,则行为未定义

现在,这里的“转换”一词用于字符串=>结果数据类型转换,不能理解为整数转换。由于转换为十进制整数的字符串 "4294967299" 无法在 32 位宽的 unsigned int 类型的对象中表示,因此标准的读取表明行为未定义,即

使用不可移植或错误程序结构或错误数据时的行为,本国际标准对此没有要求

因此,您的问题的答案是 C 标准没有说明这种情况下的行为,而您看到的行为是您的编译器和 C 库实现所展示的行为,并且不可移植;在其他平台上,可能的行为可能包括:

不可预测的结果完全忽略这种情况,在翻译或程序执行期间以环境特征的记录方式表现(无论是否发出诊断消息),终止 翻译或执行(发出诊断消息)。

【讨论】:

    【解决方案2】:

    来自this scanf (and family) reference"%u" 格式:

    数字的格式与strtoul() 所期望的相同,基参数的值为​0​(基由解析的第一个字符确定)

    然后我们进入strtoul函数,读取返回值:

    成功时str内容对应的整数值。如果转换后的值超出相应返回类型的范围,则发生范围错误并返回ULONG_MAXULLONG_MAX。如果无法进行转换,则返回​0​。

    由此我们可以看出,如果scanf"%u"格式输入的值太大,那么结果将ULONG_MAX转换为unsigned int但是sizeof(unsigned long) &gt; sizeof(unsigned int) 的系统上结果会有所不同。有关这方面的信息,请参见下文。


    需要注意的是,在 64 位 unsigned long 和 32 位 unsigned int 的平台上,unsigned long 范围内的有效值不会转换为例如UINT_MAX,而是使用模运算 as detailed here 进行转换。

    让我们取4294967299 之类的值。它对于 32 位 unsigned int 来说太大了,但非常适合 64 位 unsigned long。因此对strtoul 的调用不会返回ULONG_MAX,而是返回值4294967299。使用标准转换规则(链接到上面),这将导致unsigned int 值为3

    【讨论】:

    • "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."(已添加重点)。 %u 期望 formatstrtoulsubject sequence 相同,基数为 10,但主题序列就是:格式。它不能保证任何关于价值的东西,至少对于我对标准的阅读来说。如有必要,请随时纠正我的阅读。
    • @SurajJain 因为从大整数类型到较小整数类型的转换是使用模运算执行的。例如,如果unsigned long 是 64 位,unsigned int 是 32 位,那么结果就是预期的。 Read more about integer conversions here.
    • @AnttiHaapala 不是真的,它只是遵循标准的整数转换规则。 Suraj Jain 的评论中显示的大量问题是sizeof(unsigned long) &gt; sizeof(unsigned it)。转换是正确的。
    • 为什么要包含位。没有必要,除了基本的“您的系统可能有一个 32 位的unsigned int,因此......”。答案仍然是错误的和令人费解的。它将strtoul 的行为与不适用的scanf("%u", ...) 混合在一起。只有以 10 为底的主题序列的格式适用。
    • 标准中需要注意的一点是,它使用strtoul 作为u 的“格式化”示例;即使我们知道转换说明符ll 标志,即%llu 不一定由strtoul 呈现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多