编译程序:Linux 32位 vs 64位

4

我对32位和64位的区别还不太了解。我在Linux上用C++编写了程序。我想知道是什么决定了程序是32位还是64位?这是因为我是使用其他人编写的makefile来编译程序的。

我该如何检查它,并将其修改为64位?

谢谢。


1
请注意,当您更改机器字的大小时,并非所有代码都能干净地工作。干净的代码可以,但很容易做出错误的假设。经典案例就像是假设地址算术的结果适合于“int”。如果遇到问题,请务必在此处向SO提出更多问题。 - Donal Fellows
4个回答

6

要检查程序是否为64位,您可以编译并运行它。

file <name-of-the-binary>

例子:

~> file /bin/ls
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

所以,在我的系统上,/bin/ls 是32位的。

代码是编译为32位还是64位取决于您的环境和编译器设置。要编译64位程序,您需要一个64位内核一个64位的“用户空间”——特别是libc6和编译器库的64位版本。通常,您的编译器会根据您的环境选择适当的模式。

一些Linux发行版提供“混合”环境:一个64位内核,带有32位和64位库。如果您的环境是这样的,您的编译器可能会提供编译两种类型的二进制文件。如何在它们之间进行选择取决于您的硬件平台和编译器。对于x86-64平台上的gcc,编译器开关将是-m32-m64——只需查看gcc手册页即可。


1
记录一下,编译64位二进制文件并不需要64位内核。只有在想要运行已编译的程序时才是必需的。 - Magnus Hoff
1
@Magnus Hoff:记录一下,你不需要64位内核来运行64位应用程序。好吧,在Linux上是需要的,但这是Linux设计的限制。相比之下,32位XNU内核(Mac OS X内核)完全能够运行64位用户空间应用程序。 - JeremyP
@Magnus Hoff:当然你是对的。考虑到原帖的第一句话,我试图保持简单。通常,在编译后你会想要运行程序。 - Sven Marnach
不是每次都需要运行,有时您可能需要进行交叉编译并在传输到另一台机器后再运行。 - Fred Foo
1
@larsmans:这就是为什么我写了“通常”。下一个可能要指出的边界情况是,您编译64位目标文件时也不需要64位库——您只需要它们进行链接!但我非常确定这不是OP感兴趣的 :) - Sven Marnach

5
您可以使用file命令检查生成的可执行文件是32位还是64位。
然后,如已回答的那样,-m64和-m32选项可用于指示编译器。您需要拥有所有依赖项(库)。

0

更改gcc的编译选项(我认为应该是-m64而不是-m32),其中定义了编译参数。

您还应检查外部依赖项(库)是否也是64位,或者至少仍然可以从您的64位代码中使用。


-1

64位表示用64个比特(而不是32个)来表示整数。由于内存使用整数进行访问,这意味着(由于您的整数可以更大),您可以索引更多的内存。

编译64位程序的最简单方法是在64位计算机上编译它,但编译器也有标志(如其他答案中所述),但如果您的依赖项不是64位,则可能会出现问题。


3
64位是指指针的大小,而不是整型的大小。尽管许多编译器制造商选择使用相同的大小来表示整数和指针,但他们并不必须这样做,事实上,许多其他编译器选择不这样做。 - Mr Fooz
在64位环境中,编译器可能选择使用32位指针来访问内存? - SubSevn
@SubSevn:不,就像Fooz先生解释的那样,指针必须是64位的(假定是“平坦”的、非分段式的内存,这是今天的标准)。在我Linux系统上使用生成64位的GCC时,它采用了64位的指针、32位的int和64位的long。 - Fred Foo
@JeremyP:那么在你的书中,8088是一种8位处理器? - Sven Marnach
@Sven Marnach:实际上是这样。我记得当时有很多广告文献把它归类为8/16位。但那与Sinclair QL相比微不足道,后者包含了一个68008处理器,并将其称为8/16/32位处理器(68008的内部寄存器宽度为32位,但数据总线宽度为8位)。 - JeremyP
显示剩余2条评论

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