%d与Long Int的含义

3
以下代码是否正确?就我理解来说,它不应该正常工作,但在Dev-C++编译器上,它确实可以。请有人详细解释一下吗?
#include<limits.h>

int main()
{
long int num_case=LONG_MAX;

scanf("%d",&num_case);

printf("%ld",num_case);
return 0;
}

谢谢


3
如果你期望输入一个长整型数,那么你应该使用 %ld 进行 scanf 。但是由于长整型比典型的整型更大,因此这并不会有任何问题。 - RageD
2
不要使用Dev-C++自带的编译器,它非常过时!请参考http://www.jasonbadams.net/20081218/why-you-shouldnt-use-dev-c/。 - ThiefMaster
3个回答

5

就像标准C库告诉你不要做的大多数事情一样,它会调用未定义行为。未定义意味着它在某些条件下可能有效,但在最不希望发生的时候崩溃。

在这种情况下,它有效是因为long intint实际上是相同的数字表示形式:四个字节,二进制补码。在另一个平台(例如x86-64 Linux)上,情况可能并非如此,您可能会看到某种问题。特别是,8字节的long int的高位字节将保持未初始化状态。

编辑:问“但它会崩溃吗”是错误的思考方式。根据语言标准,仅将未初始化的字节读入long int类型的变量就可以使C程序崩溃。我们不需要找到一个这样做的平台的示例,就能理解该程序是不规范的。这就是关键所在。C不会立即向您抛出规则书,而是等待您移植和打破最初的假设。


这是除非x86-64是Windows,其中long int保持32位。 - dbrank0
1
真的会有问题吗?我的意思是,这个数字不会代表我们想要的东西,但这不会以任何方式导致程序崩溃,对吗?就64位而言,唯一真正的64位整数类型是long long,在C99中引入,并作为C++11标准的一部分。 - Geoffroy
1
@Geoffroy 运行未初始化或意外值的程序很可能会导致崩溃,尽管我从未提到过崩溃;我说的是“某种问题”。通常,我们想要避免所有不当行为,而不仅仅是崩溃。在Mac OS和Linux上,“long”和“long long”都是64位;我不知道Windows是否会有所不同,但这并没有改变任何东西。 - Potatoswatter

1
正如RageD所说,你在scanf()调用中应该使用%ld。它能够工作的原因是因为在你的系统上(或者对我来说是这样),intlong int是相同大小的(可能是4),因此scanf()不会覆盖任何不该覆盖的内存。

0
通常在32位系统上,long int有32位(与int相同),而在64位系统上,long int有64位(与long long int相同)。如果您希望您的代码具有可移植性,请使用scanf和"%ld"。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接