C中整数的无符号和后缀
Unsigned and suffix for integer in C
下面的代码没问题,编译器不会产生任何警告。但是int
如何存储unsigned int
呢?
int c = UINT_MAX;
int d = 4294967295;
long int h = ULONG_MAX;
以下代码会产生警告,但为什么呢?这些基本上是上面 long int h
变量定义的扩展版本:
long int i = 18446744073709551615;
unsigned long int j = 18446744073709551615;
警告信息如下:
88308218/source.c:14:18: warning: integer constant is so large that it is
unsigned long int i = 18446744073709551615;
88308218/source.c:15:27: warning: integer constant is so large that it is
unsigned unsigned long int j = 18446744073709551615;
下面的代码就可以了。与上面int d
的定义类似,只是加了后缀u
。似乎类型说明符比整数后缀弱。关于存储在没有 unsigned
类型的变量中的 unsigned
值的相同问题也出现了。
long int k = 18446744073709551615u;
示例源代码如下:
#include <stdio.h>
#include <limits.h>
int main(void)
{
// how can unsigned val be stored in normal int without prop type (unsigned int)
// nor with suffix (u/U)
int c = UINT_MAX;
int d = 4294967295; // ok, same question with c
long int h = ULONG_MAX; // ok, same question with c
// the following produces warning, why? this is basically just expanded ver of h
long int i = 18446744073709551615;
long int j = 18446744073709551615u;
unsigned long int k = 18446744073709551615;
printf("%u\n", c);
printf("%u\n", d);
printf("%lu\n", h);
printf("%lu\n", i);
printf("%lu\n", j);
printf("%lu\n", k);
return 0;
}
编译结果:
$ gcc source.c
source.c: In function 'main':
source.c:12:16: warning: integer constant is so large that it is unsigned
12 | long int i = 18446744073709551615;
| ^~~~~~~~~~~~~~~~~~~~
source.c:14:25: warning: integer constant is so large that it is unsigned
14 | unsigned long int k = 18446744073709551615;
| ^~~~~~~~~~~~~~~~~~~~
来自 C11 标准 (ISO/IEC 9899:2011) http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf ,(6.4.4.1,第 55-56 页)
The type of an integer constant is the first of the corresponding list
in which its value can be represented.
int
long int
long long int
因此,默认情况下,十进制整数常量是有符号整数。我们需要为其他类型提供后缀(根据 C11 文档)。
-
how can int store unsigned int?
无法存储。正如有人在评论中指出的那样,您需要使用 -Wall -Wextra -Wpedantic
选项启用额外的警告。
-
The following code produces warning, but why?
long int i = 18446744073709551615;
unsigned long int j = 18446744073709551615;
原因:根据 C11 标准,j
仍然是 signed long integer
,因为您没有添加后缀 ul
。这就是编译器向 unsigned long integer
抛出此类警告的原因。 long integer i
无法存储该值。
how can int
store unsigned int
?
int
只存储 int
s.
在赋值之前,有一个转换为int
。当 int
范围外的整数类型值被转换为 int
时,如 int c = UINT_MAX;
中那样,该值在指定的 实现中被转换为 int
方式。避免这样的代码 - 它不可移植。
不行
以下代码产生 3 个警告。启用更多警告,如 -pedantic -Wall -Wextra -Wconversion
或寻求更好的编译器。这些警告很好地显示了转换的实现指定值。
int c = UINT_MAX;
// warning: signed conversion from 'unsigned int' to 'int' changes value from '4294967295' to '-1' [-Wsign-conversion]
int d = 4294967295;
// warning: overflow in conversion from 'long int' to 'int' changes value from '4294967295' to '-1' [-Woverflow]
long int h = ULONG_MAX;
// warning: signed conversion from 'long unsigned int' to 'long int' changes value from '18446744073709551615' to '-1' [-Wsign-conversion]
缺少 u
的十进制整数常量 18446744073709551615
是 有符号 。该值超出 long long
范围 - 因此出现警告。
long int i = 18446744073709551615;
// warning: integer constant is so large that it is unsigned
unsigned long int j = 18446744073709551615;
// warning: integer constant is so large that it is unsigned
请改用 18446744073709551615u
,因为它在 unsigned long long
范围内。
long int i = 18446744073709551615u;
仍将作为下一步的一部分发出警告:转换。现在好的 unsigned long long
常量在 long long
范围之外。
long int i = 18446744073709551615u;
// warning: signed conversion from 'long unsigned int' to 'long int' changes value from '18446744073709551615' to '-1' [-Wsign-conversion]
unsigned long int j = 18446744073709551615u;
// OK
不行
以下警告出于与上述类似的原因。
long int k = 18446744073709551615u;
// warning: signed conversion from 'long unsigned int' to 'long int' changes value from '18446744073709551615' to '-1' [-Wsign-conversion]
下面的代码没问题,编译器不会产生任何警告。但是int
如何存储unsigned int
呢?
int c = UINT_MAX;
int d = 4294967295;
long int h = ULONG_MAX;
以下代码会产生警告,但为什么呢?这些基本上是上面 long int h
变量定义的扩展版本:
long int i = 18446744073709551615;
unsigned long int j = 18446744073709551615;
警告信息如下:
88308218/source.c:14:18: warning: integer constant is so large that it is
unsigned long int i = 18446744073709551615;
88308218/source.c:15:27: warning: integer constant is so large that it is
unsigned unsigned long int j = 18446744073709551615;
下面的代码就可以了。与上面int d
的定义类似,只是加了后缀u
。似乎类型说明符比整数后缀弱。关于存储在没有 unsigned
类型的变量中的 unsigned
值的相同问题也出现了。
long int k = 18446744073709551615u;
示例源代码如下:
#include <stdio.h>
#include <limits.h>
int main(void)
{
// how can unsigned val be stored in normal int without prop type (unsigned int)
// nor with suffix (u/U)
int c = UINT_MAX;
int d = 4294967295; // ok, same question with c
long int h = ULONG_MAX; // ok, same question with c
// the following produces warning, why? this is basically just expanded ver of h
long int i = 18446744073709551615;
long int j = 18446744073709551615u;
unsigned long int k = 18446744073709551615;
printf("%u\n", c);
printf("%u\n", d);
printf("%lu\n", h);
printf("%lu\n", i);
printf("%lu\n", j);
printf("%lu\n", k);
return 0;
}
编译结果:
$ gcc source.c
source.c: In function 'main':
source.c:12:16: warning: integer constant is so large that it is unsigned
12 | long int i = 18446744073709551615;
| ^~~~~~~~~~~~~~~~~~~~
source.c:14:25: warning: integer constant is so large that it is unsigned
14 | unsigned long int k = 18446744073709551615;
| ^~~~~~~~~~~~~~~~~~~~
来自 C11 标准 (ISO/IEC 9899:2011) http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf ,(6.4.4.1,第 55-56 页)
The type of an integer constant is the first of the corresponding list in which its value can be represented.
int
long int
long long int
因此,默认情况下,十进制整数常量是有符号整数。我们需要为其他类型提供后缀(根据 C11 文档)。
-
how can int store unsigned int?
无法存储。正如有人在评论中指出的那样,您需要使用 -Wall -Wextra -Wpedantic
选项启用额外的警告。
-
The following code produces warning, but why?
long int i = 18446744073709551615; unsigned long int j = 18446744073709551615;
原因:根据 C11 标准,j
仍然是 signed long integer
,因为您没有添加后缀 ul
。这就是编译器向 unsigned long integer
抛出此类警告的原因。 long integer i
无法存储该值。
how can
int
storeunsigned int
?
int
只存储 int
s.
在赋值之前,有一个转换为int
。当 int
范围外的整数类型值被转换为 int
时,如 int c = UINT_MAX;
中那样,该值在指定的 实现中被转换为 int
方式。避免这样的代码 - 它不可移植。
不行
以下代码产生 3 个警告。启用更多警告,如 -pedantic -Wall -Wextra -Wconversion
或寻求更好的编译器。这些警告很好地显示了转换的实现指定值。
int c = UINT_MAX;
// warning: signed conversion from 'unsigned int' to 'int' changes value from '4294967295' to '-1' [-Wsign-conversion]
int d = 4294967295;
// warning: overflow in conversion from 'long int' to 'int' changes value from '4294967295' to '-1' [-Woverflow]
long int h = ULONG_MAX;
// warning: signed conversion from 'long unsigned int' to 'long int' changes value from '18446744073709551615' to '-1' [-Wsign-conversion]
缺少 u
的十进制整数常量 18446744073709551615
是 有符号 。该值超出 long long
范围 - 因此出现警告。
long int i = 18446744073709551615;
// warning: integer constant is so large that it is unsigned
unsigned long int j = 18446744073709551615;
// warning: integer constant is so large that it is unsigned
请改用 18446744073709551615u
,因为它在 unsigned long long
范围内。
long int i = 18446744073709551615u;
仍将作为下一步的一部分发出警告:转换。现在好的 unsigned long long
常量在 long long
范围之外。
long int i = 18446744073709551615u;
// warning: signed conversion from 'long unsigned int' to 'long int' changes value from '18446744073709551615' to '-1' [-Wsign-conversion]
unsigned long int j = 18446744073709551615u;
// OK
不行
以下警告出于与上述类似的原因。
long int k = 18446744073709551615u;
// warning: signed conversion from 'long unsigned int' to 'long int' changes value from '18446744073709551615' to '-1' [-Wsign-conversion]