是否必须知道机器架构才能编写代码?

假设我使用Java或Python或C ++编程来解决一个简单的问题,可能是构建TCP / UDP回送服务器或计算阶乘。 我是否要关心架构细节,即它是32位还是64位?

恕我直言,除非我正在编写与相当低级别的东西相关的东西,否则如果它的32位或64位,我就不必费心了。 我哪里错了? 或者我是对的???

适合大多数情况

运行时/语言/编译器将抽象这些细节,除非您直接处理字大小或低级别的二进制文件。

甚至字节顺序也被内核中的NIC /网络堆栈抽象化。 它是为您翻译的。 在C语言中编写套接字时,有时在发送数据时有时必须处理网络的字节顺序……但这不涉及32或64位差异。

处理二进制数据blob时,将它们从一个体系结构映射到另一个体系结构(例如,作为C结构的覆盖)可能会引起其他人提到的问题,但这就是我们基于字符等开发独立于体系结构的协议的原因。

事实上像Java这样的东西在虚拟机中运行,它将机器抽象化了一步!

了解架构的指令集,以及如何编译语法可以帮助您理解平台并编写更清晰,更严格的代码。 我知道在学习编译器之后我会对一些旧的C代码做鬼脸!

了解事物是如何工作的,无论是虚拟机如何工作,它如何在您的平台上工作,或者某些C ++构造如何转换为汇编都将使您成为更好的程序员,因为您将理解为什么事情应该以他们的方式完成是。

您需要了解内存之类的内容,以了解缓存未命中的内容以及这些内容可能会影响您的程序的原因。 您应该知道某些事情是如何实现的,即使您可能只使用接口或高级方式来实现它,知道它是如何工作的,将确保您以最佳方式执行它。

对于数据包工作,您需要了解数据如何存储在平台上以及如何通过网络将数据发送到不同的平台可能会改变数据的读取方式(endian-ness)。

您的编译器将充分利用您正在编译的平台,因此只要您坚持使用标准和代码,您就可以忽略大多数事情,并假设编译器会扼杀最好的东西。

所以简而言之,没有。 你不需要知道低级别的东西,但知道永远不会伤害

你有时候必须打扰。

当这些低级细节突然跳出来咬你时,你会感到惊讶。 例如,Java标准化为64位。 但是,Linux JVM使用“扩展精度”模式,当double为80位时,只要它在CPU寄存器中。 这意味着以下代码可能会失败:

 double x = fun1(); double y = x; System.out.println(fun2(x)); assert( y == x ); 

只是因为y被强制从寄存器中移出到内存中并被截断为80到64位。

我最后一次看Java语言规范时,它在整数拳击部分中包含了一个荒谬的陷阱。

 Integer a = 100; Integer b = 100; System.out.println(a == b); 

这保证打印true

 Integer a = 300; Integer b = 300; System.out.println(a == b); 

这不保证打印为true 。 这取决于运行时。 该规格使它完全打开。 这是因为在-128和127之间装入一个int会返回“interned”对象(类似于字符串文字被插入的方式),但是如果他们愿意的话,鼓励语言运行时的实现者提高该限制。

我个人认为这是一个疯狂的决定,我希望他们已经修好了(写一次,在任何地方运行?)

在Java和Python中,体系结构细节被抽象掉,因此编写依赖于体系结构的代码实际上或多或少是不可能的。

使用C ++,这是一个完全不同的问题 – 你当然可以编写不依赖于体系结构细节的代码,但是你要小心避免陷阱,特别是关于与体系结构相关的基本数据类型,例如int

只要你正确地做事,你几乎不需要知道大多数语言。 在许多情况下,您永远不需要知道,因为语言行为不会发生变化(例如,Java会精确地指定运行时行为)。

在C ++和C中,正确地执行操作包括不对int进行假设。 不要将指针放在int中,当你对内存大小或地址做任何事情时,请使用size_t和ptrdiff_t。 不要指望数据类型的大小:int必须至少为16位,几乎总是32,在某些体系结构上可能为64。 不要认为浮点运算将在不同的机器上以完全相同的方式完成(IEEE标准中有一些余地)。

几乎所有支持网络的操作系统都会为您提供一些处理可能的字节序问题的方法。 使用它们。 使用像isalpha()这样的语言工具来对字符进行分类,而不是对字符进行算术运算(这可能是像EBCDIC一样奇怪的东西)。 (当然,现在更常见的是使用wchar_t作为字符类型,并在内部使用Unicode。)

如果您使用Python或Java编程,则解释器和虚拟机分别抽象该体系结构的这一层。 然后,您不必担心它是在32位还是64位架构上运行。

对于C ++来说也是如此,如果你在32或64位机器上运行,你有时会问自己

只有当您通过电线发送和接收原始C结构时,您才需要关心“endian-ness”

 ret = send(socket,&myStruct,sizeof(myStruct));

但是,这不是推荐的做法。

建议您在各方之间定义协议,这与各方的机器架构无关。

在C ++中,如果要编写在32位或64位上无差别工作的代码,则必须非常小心。 例如,许多人错误地认为int可以存储指针。

使用java和.net,除非你做的是非常低级的东西,比如twiddling bits,否则你真的不必费心去做。 如果你正在使用c,c ++,fortran,你可能会过去,但我实际上建议使用像“stdint.h”之类的东西,你可以使用像uint64_t和uint32_t这样的权威声明来明确。 此外,您需要根据链接方式构建特别库,例如64位系统可能在默认的64位编译模式下使用gcc。

32位计算机将允许您拥有最多4 GB的可寻址虚拟内存。 (实际上,它甚至可以小于2 GB或3 GB,具体取决于操作系统和各种链接器选项。)在64位计算机上,您可以拥有一个巨大的虚拟地址空间(在任何实际意义上,仅受磁盘限制) )和一个非常该死的大RAM。

因此,如果你期望6GB的数据集用于某些计算(让我们说需要不连贯的访问,并且不能一次只流一点),在64位架构上你可以把它读入RAM并做你的东西,而在32位架构上,您需要一种根本不同的方法来处理它,因为您根本没有选择保持整个数据集驻留。