简体   繁体   English

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

[英]What happens when I assign long int to int in C?

In a recent homework assignment I've been told to use long variable to store a result, since it may be a big number. 在最近的家庭作业中,我被告知使用long变量来存储结果,因为它可能是一个很大的数字。

I decided to check will it really matter for me, on my system (intel core i5/64-bit windows 7/gnu gcc compiler) and found out that the following code: 我决定检查它对我来说真的很重要,在我的系统上(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));

produces the following output: 产生以下输出:

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

In other words, on my system, int and long are the same, and whatever will be too big for int to hold, will be too big for long to hold as well. 换句话说,在我的系统上, intlong是相同的,并且对于int任何太大都不能保持,也不会long持有。

The homework assignment itself is not the issue here. 家庭作业本身不是问题。 I wonder how, on a system where int < long , should I assign an int to long? 我想知道在一个int < long的系统上,我应该如何为long分配一个int

I'm aware to the fact that there are numerous closely related questions on this subject, but I feel that the answers within these do not provide me with the complete understanding of what will or may happen in the process. 我知道一个事实,即存在 许多 密切 相关的关于这个问题的问题,但我觉得在这些问题的答案没有给我提供什么将会或可能在这个过程中发生了全面的了解。

Basically I'm trying to figure out the following: 基本上我想弄清楚以下内容:

  1. Should I cast long to int before the assignment, or 我应该在转让之前将longint ,或者 since long is not a different data type, but merely a modifier, 因为long不是一个不同的数据类型,而只是一个修饰符, it will be considered unharmful to assign directly? 直接分配会被视为无害吗?
  2. What happens on systems where long > int ? long > int系统上会发生什么? Will the result be undefined (or unpredictable) or it will cause the extra parts of the variable to be omitted? 结果是不确定的(或不可预测的)还是会导致变量的额外部分被省略?
  3. How does the casting from long to int works in C? longint的转换如何在C中工作?
  4. How does the assignment from long to int works in C when I don't use casting? 当我不使用强制转换时,从longint的赋值如何在C中起作用?

The language guarantees that int is at least 16 bits, long is at least 32 bits, and long can represent at least all the values that int can represent. 该语言保证int至少为16位, long至少为32位, long可以至少表示int可以表示的所有值。

If you assign a long value to an int object, it will be implicitly converted. 如果为int对象分配long值,则会隐式转换它。 There's no need for an explicit cast; 没有必要进行明确的演员表演; it would merely specify the same conversion that's going to happen anyway. 它只会指定将要发生的相同转换。

On your system, where int and long happen to have the same size and range, the conversion is trivial; 在你的系统上, intlong恰好具有相同的大小和范围,转换是微不足道的; it simply copies the value. 它只是复制价值。

On a system where long is wider than int , if the value won't fit in an int , then the result of the conversion is implementation-defined. longint宽的系统上,如果该值不适合int ,则转换的结果是实现定义的。 (Or, starting in C99, it can raise an implementation-defined signal, but I don't know of any compilers that actually do that.) What typically happens is that the high-order bits are discarded, but you shouldn't depend on that. (或者,从C99开始,它可以引发实现定义的信号,但我不知道任何编译器实际上是这样做的。) 通常发生的是高位比特被丢弃,但你不应该依赖在那。 (The rules are different for unsigned types; the result of converting a signed or unsigned integer to an unsigned type is well defined.) (对于无符号类型,规则是不同的;将有符号或无符号整数转换为无符号类型的结果已经明确定义。)

If you need to safely assign a long value to an int object, you can check that it will fit before doing the assignment: 如果需要为int对象安全地分配long值,可以在执行赋值之前检查它是否合适:

#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? */
}

The details of "something else" are going to depend on what you want to do. “别的东西”的细节将取决于你想做什么。

One correction: int and long are always distinct types, even if they happen to have the same size and representation. 一个更正: intlong 总是不同的类型,即使它们碰巧具有相同的大小和表示。 Arithmetic types are freely convertible, so this often doesn't make any difference, but for example int* and long* are distinct and incompatible types; 算术类型可以自由转换,因此这通常没有任何区别,但是例如int*long*是不同且不兼容的类型; you can't assign a long* to an int* , or vice versa, without an explicit (and potentially dangerous) cast. 如果没有明确的(也可能是危险的)强制转换,你不能将long*赋给int* ,反之亦然。

And if you find yourself needing to convert a long value to int , the first thing you should do is reconsider your code's design. 如果您发现自己需要将long值转换为int ,那么您应该做的第一件事就是重新考虑代码的设计。 Sometimes such conversions are necessary, but more often they're a sign that the int to which you're assigning should have been defined as a long in the first place. 有时候这种转换是必要的,但更常见的是,它们表明你所分配的int应该首先被定义为long

A long can always represent all values of int . long总是可以表示int所有值。 If the value at hand can be represented by the type of the variable you assign to, then the value is preserved. 如果手头的值可以由您指定的变量的类型表示,则保留该值。

If it can't be represented, then for signed destination type the result is formally unspecified, while for unsigned destination type it is specified as the original value modulo 2 n , where n is the number of bits in the value representation (which is not necessarily all the bits in the destination). 如果无法表示,则对于签名目标类型,结果是正式未指定的,而对于无符号目标类型,它被指定为模2 n的原始值,其中n是值表示中的位数(不是必然是目的地的所有比特)。

In practice, on modern machines you get wrapping also for signed types. 实际上,在现代机器上,您也可以为签名类型进行包装。

That's because modern machines use two's complement form to represent signed integers, without any bits used to denote "invalid value" or such – ie, all bits used for value representation. 这是因为现代机器使用二进制补码形式来表示有符号整数,而没有任何位用于表示“无效值”等 - 即用于表示值的所有位。

With n bits value representation any integer value is x is mapped to x +K*2 n with the integer constant K chosen such that the result is in the range where half of the possible values are negative. 对于n位值表示,任何整数值x被映射到x + K * 2 n ,其中选择的整数常数K使得结果处于可能值的一半为负的范围内。

Thus, for example, with 32-bit int the value -7 is represented as bitpattern number -7+2 32 = 2 32 -7, so that if you display the number that the bitpattern stands for as unsigned integer, you get a pretty large number. 因此,例如,使用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. 类似地,对于十进制数字系统,有十个补码和niners补码。 With 4 digit ten's complement representation you would represent -7 as 10000-7 = 9993. That's all, really. 使用4位十进制补码表示,您将代表-7为10000-7 = 9993.这就是全部,真的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM