56

在最近的一次家庭作业中,有人告诉我使用long变量来存储结果,因为它可能是一个很大的数字。

我决定在我的系统(intel core i5/64-bit windows 7/gnu gcc 编译器)上检查它对我来说真的很重要,并发现以下代码:

printf("sizeof(char) => %d\n", sizeof(char));
printf("sizeof(short) => %d\n", sizeof(short));
printf("sizeof(short int) => %d\n", sizeof(short int));
printf("sizeof(int) => %d\n", sizeof(int));
printf("sizeof(long) => %d\n", sizeof(long));
printf("sizeof(long int) => %d\n", sizeof(long int));
printf("sizeof(long long) => %d\n", sizeof(long long));
printf("sizeof(long long int) => %d\n", sizeof(long long int));

产生以下输出:

sizeof(char) => 1
sizeof(short) => 2
sizeof(short int) => 2
sizeof(int) => 4
sizeof(long) => 4
sizeof(long int) => 4
sizeof(long long) => 8
sizeof(long long int) => 8

换句话说,在我的系统上,intlong是相同的,任何太大而无法容纳的东西int,也将太大而long无法容纳。

家庭作业本身不是这里的问题。我想知道在 where 的系统上int < long,我应该如何分配一个intto long ?

我知道关于这个主题 许多 密切相关的问题,但我觉得这些 问题的答案并不能让我完全理解这个过程中将会发生什么或可能发生什么。

基本上我想弄清楚以下几点:

  1. 我应该在分配之前投到longint还是因为long 不是不同的数据类型,而只是一个修饰符,直接分配会被认为是无害的吗?
  2. 系统上会发生什么long > int?结果会是未定义的(或不可预测的)还是会导致变量的额外部分被省略?
  3. long从to的转换如何int在 C 中工作?
  4. 当我不使用强制转换时,从longto的分配如何在 C 中工作?int
4

2 回答 2

46

语言保证int至少是 16 位,long至少是 32 位,并且至少long可以表示所有可以表示的值。int

如果你给long一个int对象赋值,它会被隐式转换。不需要明确的演员表;它只会指定无论如何都会发生的相同转换。

在您的系统上,如果大小intlong范围恰好相同,则转换是微不足道的;它只是复制值。

long比 更宽的系统上int,如果该值不适合int,则转换的结果是实现定义的。(或者,从 C99 开始,它可以引发实现定义的信号,但我不知道有任何编译器实际上会这样做。)通常发生的情况是高位被丢弃,但你不应该依赖在那。(无符号类型的规则不同;将有符号或无符号整数转换为无符号类型的结果是明确定义的。)

如果您需要安全地long为对象赋值int,您可以在进行赋值之前检查它是否适合:

#include <limits.h> /* for INT_MIN, INT_MAX */

/* ... */

int i;
long li = /* whatever */

if (li >= INT_MIN && li <= INT_MAX) {
    i = li;
}
else {
    /* do something else? */
}

“其他”的细节将取决于你想做什么。

一个更正:int并且始终long是不同的类型,即使它们碰巧具有相同的大小和表示形式。算术类型可以自由转换,因此这通常没有任何区别,但例如和是不同且不兼容的类型;如果没有明确的(并且有潜在危险的)强制转换,您不能将 a 分配给 a ,反之亦然。int*long*long*int*

如果您发现自己需要将long值转换为int,那么您应该做的第一件事就是重新考虑您的代码设计。有时这样的转换是必要的,但更多时候它们表明int您分配的 应该long首先被定义为 a 。

于 2012-11-30T20:24:05.397 回答
3

Along总是可以表示 的所有值int。如果手头的值可以由您分配给的变量的类型表示,那么该值将被保留。

如果它不能被表示,那么对于有符号的目标类型,结果是正式未指定的,而对于无符号的目标类型,它被指定为原始值模 2 n,其中n是值表示中的位数(不是必须是目标中的所有位)。

实际上,在现代机器上,您也可以为签名类型进行包装。

这是因为现代机器使用二进制补码形式来表示有符号整数,没有任何位用于表示“无效值”等——即,所有位都用于值表示。

对于n位值表示,任何整数值x都映射到x +K*2 n,其中整数常数 K 被选择为使得结果在一半可能值为负的范围内。

因此,例如,对于 32 位int,值 -7 表示为位模式数 -7+2 32 = 2 32 -7,因此如果将位模式所代表的数字显示为无符号整数,则会得到一个非常大的数字。

The reason that this is called two's complement is because it makes sense for the binary numeral system, the base two numeral system. For the binary numeral system there's also a ones' (note the placement of the apostrophe) complement. Similarly, for the decimal numberal system there's ten's complement and niners' complement. With 4 digit ten's complement representation you would represent -7 as 10000-7 = 9993. That's all, really.

于 2012-11-30T20:36:56.673 回答