【问题标题】:What are integer literal types? And how are they stored?什么是整数文字类型?它们是如何存储的?
【发布时间】:2017-05-15 07:20:56
【问题描述】:

我刚刚开始学习 C,一个问题困扰了我一段时间。如果我写

int i = -1;
unsigned int j = 2;
unsigned int k = -2;

整数文字 -12-2 的类型是什么,它是如何转换为存储在 signed intunsigned int 中的?

有符号整数是什么意思,是变量还是整数字面量的属性?比如-2 是有符号整数而2 是无符号整数?

【问题讨论】:

  • 在 C 中,字面量是具有预定义值的常量。文字可以是任何基本数据类型,例如整数常量、浮点常量、字符常量或字符串文字。关于有符号和无符号整数,它指定了如何解释最重要的整数。在您的情况下,所有三个 -1、2 和 -2 都是整数类型。在 stackoverflow 上提出了一个关于有符号和无符号整数的差异的问题。你可以参考-stackoverflow.com/questions/3812022/…
  • @GAURANGVYAS 详细信息:奇怪的是,在 C 中,字符常量 不是char 类型,而是int 类型。 “整数字符常量的类型为int”C11 §6.4.4.4 10
  • 这里没有人提到二进制补码,即所有“整数”类型的存储方式,无论是有符号还是无符号。 (位相同,只是解释不同)见:en.wikipedia.org/wiki/Two's_complement
  • 表达式-1 不是常量(字面量)。它是一个由应用于常量1 的一元- 运算符组成的表达式。
  • @ebyrob:是的,除了二进制补码之外的表示形式很少见。但同样,二进制补码仅用于有符号类型。无符号类型使用纯二进制表示。

标签: c constants signed unsigned-integer


【解决方案1】:

首先,-1 不是整数常量。它是一个由应用于常量1 的一元- 运算符组成的表达式。

在 C99 和 C11 中,十进制整数常量的类型是 intlong intlong long int 中的第一个,它的值适合。同样,八进制或十六进制文字的类型为 intunsigned intlong intunsigned long intlong long intunsigned long long int。详情在N15706.4.4.1。

-1-2常量表达式。一元 - 运算符的结果与操作数具有相同的类型(即使该结果导致溢出,正如 -INT_MIN 在大多数实现中所做的那样)。

int i = -1;

常量1 和表达式-1 都是int 类型。该值存储在int对象i中;无需转换。 (严格来说是从int转换成int,不过没关系。)

unsigned int j = 2;

2 的类型为 int。它从int 转换为unsigned int

unsigned int k = -2;

-2 的类型为 int。它从int 转换为unsigned int。这一次,因为-2超出了unsigned int的范围,所以转换不简单;结果是UINT_MAX - 1

一些术语:

constant 是一些其他语言所称的literal。它是一个表示常量值的单个标记。例如10xff

常量表达式 是需要在编译时计算的表达式。常量是常量表达式;操作数是常量或常量表达式的表达式也是如此。例如-12+2

【讨论】:

  • 您的解释绝对精彩,脱帽致敬,我从未见过如此清晰和精彩的解释。我写了一个后续问题,,问题在这里。 "stackoverflow.com/questions/41407568/…"
  • 您说“-1 不是整数常量。它是由应用于常量 1 的一元 - 运算符组成的表达式。”但是“十进制整数常量的类型是 int、long int 或 long long int 中的第一个”,所以如果-1 不是整数常量,为什么它会有任何类型,因为类型是为整数常量定义的。跨度>
  • 每个表达式都有一个类型。
  • 十进制整数常量有以下类型,你说-1不是十进制整数常量。
  • @user7359847 几年后:没有矛盾。 1int 类型的十进制整数常量。也是一种表达方式。 -1 不是十进制整数常量,而是一个表达式,它也有int 类型。它的类型不是由十进制整数常量的规则决定的,而是由一元- 运算符的规则决定的。 “一元 - 运算符的结果是其(提升的)操作数的负数。整数提升在操作数上执行,结果具有提升的类型。”
【解决方案2】:

在 C99 和 C11 中

如果您想指定整数的类型,您可以使用integer constant

你可以用十进制、八进制或十六进制表示整数:

int decimal = 42; // nothing special
int octal = 052; // 0 in front of the number
int hexa = 0x2a; // 0x
int HEXA = 0X2A; // 0X

十进制表示:

默认情况下,-1、0、1等的类型为intlong intlong long int。编译器必须峰值可以处理您的值的类型:

int a = 1; // 1 is a int
long int b = 1125899906842624; // 1125899906842624 is a long int

这仅适用于signed 值,如果您想要unsigned 值,您需要添加 u 或 U:

unsigned int a = 1u;
unsigned long int b = 1125899906842624u;

如果你想要long intlong long int 而不是int,你可以使用l 或L:

long int a = 1125899906842624l;

你可以把 u 和 l 结合起来:

unsigned long int a = 1125899906842624ul;

最后,如果你只想要long long int,你可以使用ll或LL:

unsigned long long int a = 1125899906842624ll;

你可以再次与你结合。

unsigned long long int a = 1125899906842624ull;

八进制和十六进制表示:

如果没有后缀,整数将匹配intlong intlong long intunsigned intunsigned long intunsigned long long int

int a = 0xFFFF;
long int b = -0xFFFFFFFFFFFFFF;
unsigned long long int c = 0xFFFFFFFFFFFFFFFF;

u 与十进制表示没有区别。 l 或 L 和 ll 或 LL 添加无符号值类型。


这类似于string literals

【讨论】:

    【解决方案3】:

    整数文字 -1 和 2 和 -2 的类型是什么,它是如何转换为存储在有符号整数和无符号整数中的?

    C 解析器/编译器,正如 chux 之前所说,“理解”你的文字为有符号整数 - 总是。然后将它们转换为适合您分配给的变量,该变量可以是不同的类型。这样做,一些位可能会丢失,或者它们可能会改变它们的含义(例如,将负值分配给 unsigned int)。一些编译器可能会警告您“文字超出范围”,而其他编译器可能会默默地接受(并截断)您的文字。

    有符号整数是什么意思,是变量还是整数字面量的属性,比如-2是有符号整数,2是无符号整数。?

    它是变量的一个属性。实际上,它是一种“类型”——写成“两个词”的标识符。

    【讨论】:

      【解决方案4】:

      我会说这取决于编译器和机器的架构。给定8 bits = 1 byte,下表总结了在 32 位和 64 位机器上(有符号)intunsigned int 所需的不同 Integer 类型:

      +------+------+---------+-------+--------+-------------+-----------+ 
      |Type  |char  |short int|int    |long int|long long int|int pointer|
      +------+-------+--------+-------+--------+-------------+-----------+
      |32-bit|8 bits|16 bits  |32 bits|32 bits |64 bits      |32 bits    |
      +------+------+---------+-------+--------+-------------+-----------+
      |64-bit|8 bits|16 bits  |32 bits|64 bits |64 bits      |64 bits    | 
      +------+------+---------+-------+--------+-------------+-----------+
      

      您可能知道,(有符号)intunsigned int 之间的最大区别在于,在(有符号)int 中,最高有效位(MSB)是为整数的符号保留的,因此:

      • 具有 n 位的(有符号)int 的值可以在 -(2^(n-1))(2^(n-1))-1 之间
      • 具有 n 位的unsigned int 可以具有介于0(2^n)-1 之间的值

      现在,我们可以计算不同(单点)int 类型的范围(可能值),如下所示:

      +------+---------+----------+----------+----------+-------------+-----------+
      |Type  |char     |short int |int       |long int  |long long int|int pointer|
      +------+---------+----------+----------+----------+-------------+-----------+
      |32-bit|-(2^7) to|-(2^15) to|-(2^31) to|-(2^31) to|-(2^63) to   |-(2^31) to |
      |      |+(2^7)-1 |+(2^15)-1 |+(2^31)-1 |+(2^31)-1 |+(2^63)-1    |+(2^31)-1  |
      +------+---------+----------+----------+----------+-------------+-----------+
      |64-bit|-(2^7) to|-(2^15) to|-(2^31) to|-(2^63) to|-(2^63) to   |-(2^63) to |
      |      |+(2^7)-1 |+(2^15)-1 |+(2^31)-1 |+(2^63)-1 |+(2^63)-1    |+(2^63)-1  |
      +------+---------+----------+----------+----------+-------------+-----------+
      

      此外,我们可以计算不同unsigned int类型的范围(可能值)如下:

      +------+-------+----------+-------+--------+-------------+-----------+
      |Type  |char   |short int|int     |long int|long long int|int pointer|
      +------+-------+---------+--------+--------+-------------+-----------+
      |32-bit|0 to   |0 to     |0 to    |0 to    |0 to         |0 to       |
      |      |(2^8)-1|(2^16)-1 |(2^32)-1|(2^32)-1|(2^64)-1     |(2^32)-1   |
      +------+-------+---------+--------+--------+-------------+-----------+
      |64-bit|0 to   |0 to     |0 to    |0 to    |0 to         |0 to       |
      |      |(2^8)-1|(2^16)-1 |(2^32)-1|(2^64)-1|(2^64)-1     |(2^64)-1   |
      +------+-------+---------+--------+--------+-------------+-----------+
      

      最后,要了解我们如何以及为什么在 32 位机器上使用 8 字节(64 位)存储 long long int,请参阅 this post

      【讨论】:

      • 带符号整数的范围不正确。由于 MSB 不仅仅是一个符号位,而且在大多数机器上都使用二进制补码,因此负值比正值多一个。你也需要一点点。对于有符号整数,范围是 -(2^(n-1)) .. 2^(n-1)-1。您的公式将导致 -257..255 为 char 而它是 -128..127
      • 好收获!我修复了公式并更新了表格!
      • 我刚刚看到无符号值也是“减 1”。它们从 0 变为 (2^n) -1。除此之外,32 位和 64 位机器的数据类型的大小不是固定的。在 64 位机器上,您还可以获得 64 位整数。
      • 好吧,再来一个!我敢打赌你找不到第三个!感谢您帮助改进此答案! :-)
      • 它是如何回答这个问题的?它在哪里说整数常量1 的类型是什么?无论机器如何,它始终是int 类型。引用 6.4.4 中的表格也比整个话题脱轨更相关。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      • 1970-01-01
      • 1970-01-01
      • 2016-09-06
      • 2011-07-06
      • 2012-03-23
      相关资源
      最近更新 更多