当我将long int分配给C中的int时会发生什么?
在最近的作业任务中,我被告知使用long
variables来存储结果,因为它可能是一个很大的数字。
我决定检查一下对我来说真的很重要,在我的系统上(intel core i5 / 64-bit windows 7 / gnu gcc compiler),发现下面的代码:
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
换句话说,在我的系统中, int
和long
是相同的,并且对于int
来说太大的东西long
不能容纳。
家庭作业本身不是问题。 我不知道如何,在一个系统int < long
,我应该分配一个int
长?
我知道在这个问题上有 很多 密切 相关的问题,但是我觉得这些问题的答案并不能让我完全理解这个过程中会发生什么。
基本上我试图找出以下几点:
- 我应该在转让前
long
投入int
,还是因为直接分配将被认为是无害的?long
不是一个不同的数据types,而只是一个修饰符, - 在
long > int
系统上会发生什么? 结果是不确定的(或不可预测的),否则会导致variables的多余部分被忽略? - 如何从C到C的
long
int
工作? - 当我不使用cast时,从
long
到int
的赋值在C中是如何工作的?
该语言保证int
至less为16位, long
至less为32位,而long
至less可以表示int
可以表示的所有值。
如果将一个long
值赋给一个int
对象,它将被隐式转换。 不需要明确的演员, 它只会指定无论如何将发生相同的转换。
在你的系统中, int
和long
有相同的大小和范围,转换是微不足道的; 它只是复制值。
在long
比int
更宽的系统上,如果该值不适合int
,那么转换的结果是实现定义的。 (或者,从C99开始,它可以引发一个实现定义的信号,但我不知道有任何编译器会这样做。) 通常发生的事情是高位被丢弃,但不应该依赖在那。 (对于无符号types,规则是不同的;将有符号或无符号整数转换为无符号types的结果已经很好的定义了。)
如果您需要安全地为int
对象分配一个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
总是不同的types,即使它们恰好具有相同的大小和表示forms。 算术types是可自由转换的,所以这通常不会有任何区别,但是例如int*
和long*
是不同的和不兼容的types; 你不能指定一个long*
到一个int*
,反之亦然,没有明确的(和潜在危险的)强制转换。
如果你发现自己需要将一个long
值转换为int
,那么你应该做的第一件事是重新考虑你的代码的devise。 有时候这样的转换是必要的,但是更多的时候它们是一个标志,你所分配的int
应该被定义为一个long
int
。
long
可以总是表示int
所有值。 如果手头的值可以用您指定的variables的types来表示,那么该值将被保留。
如果不能表示,那么对于带符号的目标types,结果是正式未指定的,而对于无符号的目标types,它指定为原始值模2 n ,其中n是值表示中的位数(不是必须在目标中的所有位)。
在实践中,在现代机器上,你也可以打包签名types。
这是因为现代机器使用二进制补码forms来表示带符号的整数,而不用任何用来表示“无效值”的位,即用于值表示的所有位。
用n位值表示任何整数值x被映射到x + K * 2 n ,其中整数常数K被select成使得结果在可能值的一半为负的范围内。
因此,例如,对于32位int
,值-7表示为位模式编号-7 + 2 32 = 2 32 -7,因此如果显示bitpattern代表的数字为无符号整数,则会得到一个漂亮大数字。
这被称为二进制补码的原因是因为它对于二进制数字系统,基本的两个数字系统是有意义的。 对于二进制数字系统,还有一个'(注意撇号的位置)补码。 同样,对于十进制数字系统,有十进制补码和补码。 用4位十进制补码表示,你可以将-7表示为10000-7 = 9993.这就是真的。