当我在C中将long int分配给int时会发生什么?

时间:2012-11-30 20:19:40

标签: c casting integer variable-assignment long-integer

在最近的家庭作业中,我被告知使用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保持住。

家庭作业本身不是问题所在。我想知道,在int < long的系统中,我应该如何将int分配给长?

我知道there are numerous closely related关于此主题的问题,但我觉得这些问题的答案是没有让我完全理解这个过程中会发生什么或可能发生什么。

基本上我想弄清楚以下内容:

  1. 我应该在分配前将long转换为int,还是从long转换为 不是一个不同的数据类型,而只是一个修饰符,它将是 被认为是无害的直接分配?
  2. long > int的系统上会发生什么?结果会是 未定义(或不​​可预测)或它将导致的额外部分 要省略的变量?
  3. longint的投射如何在C?中起作用?
  4. 如果不这样做,longint的作业如何在C中发挥作用 用铸造?

2 个答案:

答案 0 :(得分:42)

该语言保证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? */
}

“别的东西”的细节将取决于你想做什么。

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

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

答案 1 :(得分:4)

long始终代表int的所有值。 如果手头的值可以由您指定的变量的类型表示,则保留该值。

如果无法表示,则对于带符号的目标类型,结果是正式未指定的,而对于无符号目标类型,它被指定为原始值modulo 2 n ,其中 n 是值表示中的位数(不一定是目标中的所有位)。

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

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

使用 n 位值表示任何整数值 x 映射到 x + K * 2 n < / i> 选择整数常数K,使得结果在一半可能值为负的范围内。

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

这被称为二的补码的原因是因为它对二进制数字系统有意义,基本的两个数字系统。对于二进制数字系统,还有一个'(注意撇号的位置)补码。类似地,对于十进制数字系统,有十个补码和niners补码。使用4位十进制补码表示,您将代表-7为10000-7 = 9993.这就是全部,真的。