【问题标题】:Question about C datatype and constant关于C数据类型和常量的问题
【发布时间】:2011-07-20 17:51:23
【问题描述】:

您好! 我一直在用 C 语言做实验,直到我遇到了一些非常奇怪的东西。 我无法解释下面显示的结果。

守则:

#include <stdio.h>

int main(void)
{
    int num = 4294967295U;
    printf("%u\n", num);
    return 0;
}

问题:

1.) 如您所见,我创建了一个 int,它可以保存 -21474836482147483647 之间的数字。

2.) 当我将值 4294967295 分配给此变量时,由于变量溢出,IDE 会在编译期间向我显示一条警告消息。

3.) 出于好奇,我在数字后面添加了一个 U (unsigned),当我重新编译它时,编译器没有返回任何警告消息。

4.) 我通过将 U (unsigned) 更改为 L (long)LL (long long) 做了进一步的实验。正如预期的那样,这两个警告消息仍然存在,但在我将其更改为 UL (unsigned Long)ULL (unsigned long long) 之后不再存在。

5.) 为什么会这样?

警告信息:(对于第 2 步)

warning #2073: Overflow in converting constant expression from 'long long int' to 'int'.

警告信息:(对于第 4 步 LLL

warning #2073: Overflow in converting constant expression from 'long long int' to 'long int'.

最后,感谢您阅读我的问题,非常感谢您的教导和建议。

【问题讨论】:

  • 我认为您正在寻找 C 中促销规则的描述。当我用谷歌搜索它们时,我在顶部找到的链接之一的标题是“整体促销:不一定是合乎逻辑。这是法律”。这是一个很好的总结,也许你可以在那篇文章中找到你需要的信息:msmvps.com/blogs/vandooren/archive/2007/10/05/…
  • 首先,int 只能保证保存从 -32767 到 32767 的值。您的平台很可能提供更宽的 ints,但这是您不能依赖的未指定行为。
  • @Thom 如果你要学究起来,整数类型可以容纳的范围是 implementation-defined,这与 unspecified 的概念不同.
  • @Pascal:这不是关于 integer Promotions,而是关于 integer constants 的类型,这是 ISO C99 6.4.4.1 Semantics .
  • @caramel23:您发布的代码显然不是您正在测试的代码。您引用的警告消息谈到从long long intlong int 的转换。 long long int 显然是您通过使用后缀 LL 提供的常量类型。但是long int 是从哪里来的呢?我在您的代码中没有看到任何 long ints。你确定num 在你收到警告信息时被声明为int 而不是long int

标签: c variables integer constants


【解决方案1】:

根据 ISO C99 标准,第 6.4.4.1 节(整数常量),语义小节,整数常量的类型是下表的第一种类型值可以在哪里表示:

                                    Octal or Hexadecimal
Suffix            Decimal Constant            Constant
none         int                    int
             long int               unsigned int
             long long int          long int
                                    unsigned long int
                                    long long int
                                    unsigned long long int

u or U       unsigned int           unsigned int
             unsigned long int      unsigned long int
             unsigned long long int unsigned long long int

l or L       long int               long int
             long long int          unsigned long int
                                    long long int
                                    unsigned long long int

both u or U  unsigned long int      unsigned long int
and l or L   unsigned long long int unsigned long long int

ll or LL     long long int          long long int
                                    unsigned long long int

both u or U  unsigned long long int unsigned long long int
and ll or LL

特定的实现可以具有扩展的整数类型,它们遵循与上述相同的模式。

【讨论】:

  • 同样在6.3.1.3/3中声明“新类型是有符号的,值不能在其中表示;结果是implementation-defined。”
  • 对不起,我忘记添加另一个警告消息,我只是通过添加另一个警告消息来编辑它
【解决方案2】:

也许,默认情况下,编译器假定您输入的是有符号整数。当您给它4294967295 时,该数字不适合 4 字节整数,因此它使用 8 字节整数来存储它。然后它必须进行有损转换(long long,AKA 8 字节,到 long,AKA 4 字节),所以它会给你一个警告。

但是,当您键入4294967295U 时,它知道您需要一个无符号整数。该数字适合一个 4 字节的无符号整数,因此它的类型为 long int,并且不需要有损转换。 (从unsigned long intlong int 并没有丢失数据,只是错误地表示它。)

【讨论】:

  • 抱歉,我忘记添加另一个警告消息,我只是通过添加另一个警告消息来编辑它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多