我刚刚开始学习C,一个问题困扰了我一段时间。如果我写
int i = -1;
unsigned int j = 2;
unsigned int k = -2;
整数文字-1
和2
和-2
的类型是什么,它如何转换为存储在signed int
和unsigned int
中?
有符号整数是什么意思,这也是变量或整数文字的属性吗?比如-2
是有符号整数,2
是无符号整数?
首先,-1
不是一个整数常量。它是一个表达式,由应用于常量1
的一元-
运算符组成。
在 C99 和 C11 中,十进制整数常量的类型是其值适合的int
、long int
或long long int
中的第一个。类似地,八进制或十六进制文本的类型为int
、unsigned int
、long int
、unsigned long int
、long long int
或unsigned long long int
。详细信息在 N1570 6.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
.
一些术语:
常量是其他一些语言所说的文字。它是表示常量值的单个令牌。例子是1
和0xff
.
常量表达式是需要在编译时计算的表达式。常量是常量表达式;操作数为常量或常量表达式的表达式也是如此。示例是-1
和2+2
.
在 C99 和 C11 中
如果要指定整数的类型,可以使用整数常量:
您可以使用十进制、八进制或十六进制表示形式编写整数:
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 等的类型为int
、long int
或long 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 int
或long 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;
八进制和十六进制表示:
没有后缀,整数将与int
、long int
、long long int
、unsigned int
、unsigned long int
和unsigned long long int
匹配。
int a = 0xFFFF;
long int b = -0xFFFFFFFFFFFFFF;
unsigned long long int c = 0xFFFFFFFFFFFFFFFF;
u 与十进制表示形式没有区别。 l 或 L 和 ll 或 LL 添加无符号值类型。
这类似于字符串文本。
文字 -1 和 2 和 -2 的类型是什么,它如何转换为存储在有符号的 int 和无符号 int 中?
C 解析器/编译器,正如 chux 之前所说,将您的文字"理解"为有符号整数 - 始终。然后,它们被强制转换为适合您分配给的变量,该变量可以是不同类型的变量。这样做,某些位可能会丢失,或者它们可能会改变其含义(例如,为无符号的 int 分配负值)。一些编译器可能会警告你"文字超出范围",其他编译器可能会默默地接受(并截断)你的文字。
有符号整数是什么意思,变量或整数文字的属性也是,比如-2是有符号整数,2是无符号整数。?
它是变量的属性。实际上,它是一个"类型"——写成"两个词"标识符。
我想说这取决于编译器和机器的架构。给定8 bits = 1 byte
,下表汇总了 32 位和 64 位计算机上(有符号)int
和unsigned int
的不同整数类型及其所需大小:
+------+------+---------+-------+--------+-------------+-----------+
|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 |
+------+------+---------+-------+--------+-------------+-----------+
如您所知,(有符号)int
和unsigned int
之间的最大区别在于,在(有符号)int
中,最高有效位 (MSB) 是为整数的符号保留的,因此:
- 具有 n 位的 a(有符号)
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
,请参阅这篇文章。