6

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

恕我直言,除非我正在编写与相当低级的东西有关的东西,否则我不必担心它是 32 位还是 64 位。我哪里错了?还是我说的对???

4

11 回答 11

16

在大多数情况下都是正确的

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

甚至字节顺序也被内核中的 NIC/网络堆栈抽象出来。它是为你翻译的。在 C 中编程套接字时,有时您必须在发送数据时处理网络的字节顺序……但这与 32 位或 64 位差异无关。

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

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

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

于 2009-06-25T20:34:25.887 回答
16

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

您需要了解诸如内存之类的东西,以了解缓存未命中是什么以及为什么这些可能会影响您的程序。您应该知道某些事情是如何实现的,即使您可能只使用接口或高级方式来实现它,但知道它是如何工作的将确保您以最好的方式完成它。

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

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

所以简而言之,没有。你不需要知道底层的东西,但知道它永远不会有坏处

于 2009-06-25T20:37:48.373 回答
8

上次我查看 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”对象(类似于字符串文字的 interned 方式),但如果语言运行时的实现者愿意,我们鼓励他们提高该限制。

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

于 2009-06-25T20:53:07.050 回答
6

你有时必须打扰。

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

double x = fun1();
double y = x;

System.out.println(fun2(x));

assert( y == x );

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

于 2009-06-25T20:46:39.463 回答
3

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

对于 C++,这是完全不同的事情——你当然可以编写不依赖于架构细节的代码,但你要小心避免陷阱,特别是与架构相关的基本数据类型,例如int.

于 2009-06-25T20:40:07.433 回答
2

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

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

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

于 2009-06-25T20:46:48.683 回答
1

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

对于 C++ 则不能这样说,在 C++ 中,您有时不得不问自己是在 32 位还是 64 位机器上运行

于 2009-06-25T20:39:10.807 回答
0

使用 java 和 .net,除非您正在做非常低级的事情,例如玩弄比特,否则您实际上不必费心。如果您使用的是 c、c++、fortran,您可能会过得去,但我实际上建议您使用诸如“stdint.h”之类的东西,您可以在其中使用像 uint64_t 和 uint32_t 这样的明确声明,以便明确。此外,您将需要根据您的链接方式使用特定的库进行构建,例如,64 位系统可能在默认的 64 位编译模式下使用 gcc。

于 2009-06-25T21:12:29.600 回答
0

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

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

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

建议您在各方之间定义一个协议,这样各方的机器架构就无关紧要了。

于 2009-06-25T20:34:35.840 回答
0

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

因此,如果您期望 6GB 数据集用于某些计算(假设需要不连贯的访问并且不能一次只流一点),在 64 位架构上,您可以将其读入 RAM 并执行您的操作,而在 32 位架构上,您需要一种完全不同的方法来处理它,因为您根本无法选择保持整个数据集驻留。

于 2009-06-25T23:43:56.313 回答
0

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

于 2009-06-25T20:35:52.997 回答