ChatGPT解决这个技术问题 Extra ChatGPT

为什么 Java 不支持无符号整数?

为什么 Java 不包含对无符号整数的支持?

在我看来,这是一个奇怪的遗漏,因为它们允许人们编写不太可能在意外大输入时产生溢出的代码。

此外,使用无符号整数可以是一种自我证明的形式,因为它们表明无符号整数打算保存的值永远不会是负数。

最后,在某些情况下,无符号整数对于某些操作(例如除法)可能更有效。

包含这些有什么缺点?

我不知道,但这让我很恼火;例如,以这种方式编写网络代码要困难得多。
我希望语言/数据库/...世界中只有两种类型:数字和字符串:)
编写网络代码一点也不难。顺便说一句,InputStream.read() 返回一个无符号字节,而不是一个有符号的字节,所以网络示例是一个混淆恕我直言。唯一令人困惑的是您认为编写有符号值与编写无符号值有任何不同。即,如果您实际上不知道字节级别发生了什么。
@ZachSaw - 当我看到一位语言设计师提出这句话时,我也做了双重考虑。没有什么比无符号整数更简单的了。有符号整数很复杂。特别是当您考虑在晶体管级别上旋转的位时。有符号整数如何移位?我不得不得出结论,Java 的设计者在理解布尔逻辑方面存在严重问题。
对我来说,使用图像 byte 无法提供直接的 140 灰度级但需要 & 0xff 才能获得正确值的 -116 进行任何图像处理变得更加困难。

E
Erik Kaplun

这是来自 interview with Gosling and others,关于简单性:

Gosling:作为一名语言设计师,我现在并不认为自己是这样的,“简单”最终的真正含义是我能否期望 J. Random Developer 将规范牢牢记在脑海中。该定义表明,例如,Java 不是——事实上,这些语言中的许多最终都会出现很多极端情况,即没有人真正理解的事情。向任何 C 开发人员询问有关无符号的问题,很快你就会发现几乎没有 C 开发人员真正了解无符号是怎么回事,什么是无符号算术。这样的事情使 C 变得复杂。我认为 Java 的语言部分非常简单。您必须查找的库。


我将不得不在这里举一个具体的例子(来自 CLR)不同意 Gosling。给数组一个有符号整数长度值或无符号长度更令人困惑的是什么?数组不可能有负长度,但我们的 API 表明这是可能的。
让 Java 变得简单的论点是让我们陷入缺乏模板的混乱局面的一部分,他们最终将模板引入语言,因为替代方案太麻烦了。我确实认为可以通过适当的类支持无符号整数,但它不需要 prims
如果 Java 需要无符号整数,因为数组索引不能为负数,那么它还需要子范围(a la Pascal),因为数组索引不能大于数组大小。
好的,他只是告诉了没有无符号类型的好处。现在让我们来计算缺点......
我更喜欢代码简单而不是语言简单。这就是我讨厌Java的原因。
N
Neil Coffey

在字里行间阅读,我认为逻辑是这样的:

一般来说,Java 设计者希望简化可用数据类型的全部内容

对于日常目的,他们认为最常见的需求是签名数据类型

为了实现某些算法,有时需要无符号算术,但是将实现此类算法的程序员也将具备“工作”的知识,以使用有符号数据类型进行无符号算术

大多数情况下,我会说这是一个合理的决定。可能,我会:

使字节无符号,或者至少为这种数据类型提供了可能具有不同名称的有符号/无符号替代方案(使其有符号有利于一致性,但是您何时需要有符号字节?)

取消了“short”(你最后一次使用 16 位有符号算术是什么时候?)

尽管如此,对不超过 32 位的无符号值的操作还算不错,而且大多数人不需要无符号的 64 位除法或比较。


我也希望有无符号字节,但我怀疑整数类型之间完全一致的优势超过了无符号字节带来的便利。
“对于日常目的,他们认为最常见的需求是签名数据类型”。在我的 C++ 代码中,我经常发现自己在想“为什么我在这里使用有符号整数而不是无符号整数?!”。我觉得“有符号”是例外而不是规则(当然,这取决于域,但是将正整数称为自然数是有原因的;-))。
为无符号字节的调用竖起大拇指,在进行图像处理时,假设字节是无符号的(应该是),这让我花了几个小时调试。
您会惊讶于 short 的使用频率 - defltate/gzip/inflate 算法是 16 位的,并且它们严重依赖短裤......或者至少 short[] [诚然它们是原生的 - 但算法的 java impl 携带 TB数据]。后者 (short[]) 比 int[] 具有显着优势,因为它占用更少的内存和更少的内存 = 更好的缓存属性,更好的性能。
尽管在特定的应用程序中,您应该衡量使用短裤是否会给您带来更好的性能,而不是假设它是正确的。操作短裤而不是整数(通常是处理器“喜欢使用”的类型)所需的额外的诡计可能实际上对特定应用程序的性能有害。并非总是如此,但您应该测试,而不是假设。
M
Mr. Polywhirl

这是一个较老的问题,pat 确实简要提到了 char,我只是想我应该为其他将在路上看到这个的人扩展这个。让我们仔细看看 Java 原始类型:

byte - 8 位有符号整数

short - 16 位有符号整数

int - 32 位有符号整数

long - 64 位有符号整数

char - 16 位字符(无符号整数)

虽然 char 不支持 unsigned 算术,但它本质上可以被视为 unsigned 整数。您必须将算术运算显式转换回 char,但它确实为您提供了一种指定 unsigned 数字的方法。

char a = 0;
char b = 6;
a += 1;
a = (char) (a * b);
a = (char) (a + b);
a = (char) (a - 16);
b = (char) (b % 3);
b = (char) (b / a);
//a = -1; // Generates complier error, must be cast to char
System.out.println(a); // Prints ? 
System.out.println((int) a); // Prints 65532
System.out.println((short) a); // Prints -4
short c = -4;
System.out.println((int) c); // Prints -4, notice the difference with char
a *= 2;
a -= 6;
a /= 3;
a %= 7;
a++;
a--;

是的,没有对无符号整数的直接支持(显然,如果有直接支持,我不必将大部分操作转换回 char )。但是,肯定存在无符号原始数据类型。我也希望看到一个无符号字节,但我想将内存成本加倍,而使用 char 是一个可行的选择。

编辑

对于 JDK8,有用于 LongInteger 的新 API,它们在将 longint 值视为无符号值时提供帮助方法。

比较无符号

除无符号

parseUnsignedInt

parseUnsignedLong

余数无符号

toUnsignedLong

toUnsignedString

此外,Guava 提供了许多帮助方法来对整数类型执行类似的操作,这有助于缩小因缺乏对 unsigned 整数的本机支持而留下的差距。


但是,例如,char 太小而无法支持 long 算术。
这可能是 Java 的一个缺点
希望他们支持字节的无符号值。让事情变得更容易。
我在尝试从硬盘驱动器读取数据时遇到了这个问题,该硬盘驱动器是由 C 程序写入的,该程序具有 C 结构规范。我被迫不仅要处理 Endian 差异,而且还要雪上加霜,使用 64 位整数读取所有内容,然后应用移位操作来获取正确的数据,只是因为有人决定他们不想实现无符号数。抱歉,如果他们被允许说“保持 Java 简单”之类的话,那么我会说这是一个懒惰的原因。
p
pat

Java 确实有无符号类型,或者至少有一种: char 是无符号短类型。所以无论高斯林抛出什么借口,这实际上只是他的无知,为什么没有其他无符号类型。

也短类型:短裤一直用于多媒体。原因是您可以在单个 32 位无符号长整数中拟合 2 个样本并矢量化许多操作。 8 位数据和无符号字节也是如此。您可以将 4 或 8 个样本放入寄存器中以进行矢量化。


是的,与您相比,我敢肯定 Gosling 对 Java 非常无知。
Java 是否允许直接在无符号字节数量上执行算术运算,还是总是提升值?具有用于存储的无符号类型,但始终对足够大以容纳它的有符号类型执行算术在语义上效果很好,但会导致对与“正常”整数大小相同的无符号类型的操作更加昂贵。
char 用于除字符之外的任何内容都是不好的风格。
@starblue 当然是,但是绕过语言限制是一种技巧
P
Perception

一旦有符号和无符号整数在表达式中混合,事情就会开始变得混乱,您可能会丢失信息。将 Java 限制为已签名的整数只会真正解决问题。我很高兴我不必担心整个已签名/未签名的业务,尽管我有时确实会错过一个字节中的第 8 位。


至于混合有符号/无符号:您可以有无符号类型,但不允许混合(或需要显式强制转换)。不过,还不清楚是否有必要。
在 C++ 中,您必须在周围撒很多 static_cast 来混合它们。确实很乱。
第 8 位在那里,它只是试图将自己隐藏为标志。
只有 32 位或更大的类型才会让事情变得混乱。我认为 Java 没有任何理由不应该像在 Pascal 中那样对 byte 进行签名。
当您在 Java 中遇到图像处理问题时来找我,您希望字节是无符号的。然后您就会知道,& 0xFF 执行每个字节到整数的提升会使代码更加混乱。
a
akatakritos

http://skeletoncoder.blogspot.com/2006/09/java-tutorials-why-no-unsigned.html

这家伙说,因为 C 标准定义了涉及无符号和有符号整数的操作被视为无符号。这可能会导致负符号整数滚动到一个大的无符号整数,从而可能导致错误。


Java 有符号整数也会滚动。我不明白你的意思。
@foo:有符号整数在引起问题之前必须变大。相比之下,在 C 中,将任何负整数(甚至 -1)与任何无符号量(甚至零)进行比较都可能会遇到问题。
太糟糕了,Java 不能包含无符号类型,但转换和混合运算符的集合有限(有点类似于在 C 中可以将 5 加到指针上,但不能将指针与 5 进行比较) .当存在隐式转换时,在混合类型上使用运算符应该强制隐式使用该转换(并将结果类型用作结果类型)是 .NET 和 .NET 中许多可疑设计决策的核心。爪哇。
不要对您的答案咆哮,但将 -1 作为“未知”年龄(如文章所示)是“代码异味”的经典示例之一。例如,如果您想计算“Alice 比 Bob 大多少?”,并且 A=25 和 B=-1,您将得到 ±26 的答案,这完全是错误的。当 Some(25) - None 将返回 None 时,对未知值的正确处理是某种 Option<TArg>
N
Nayuki

我认为 Java 本身就很好,添加 unsigned 会使它复杂化而没有太多收获。即使使用简化的整数模型,大多数 Java 程序员也不知道基本数字类型的行为方式 - 只需阅读本书 Java Puzzlers 以了解您可能持有哪些误解。

至于实用建议:

如果您的值有些随意大小并且不适合 int,请使用 long。如果它们不适合长期使用 BigInteger。

当您需要节省空间时,仅对数组使用较小的类型。

如果您恰好需要 64/32/16/8 位,请使用 long/int/short/byte 并停止担心符号位,除法、比较、右移和强制转换除外。

另请参阅有关“将随机数生成器从 C 移植到 Java”的 this 答案。


是的,对于右移,您必须分别在 >>>>> 之间选择有符号和无符号。左移没有问题。
@starblue 实际上 >>> 不适用于 shortbyte。例如,(byte)0xff>>>1 产生 0x7fffffff 而不是 0x7f。另一个示例:byte b=(byte)0xff; b>>>=1; 将导致 b==(byte)0xff。当然,您可以执行 b=(byte)(b & 0xff >> 1);,但这会增加一项操作(按位 &)。
“......即使使用简化的模型,大多数 Java 程序员也不知道基本数字类型的行为......” 我心里有些东西只是讨厌一种针对最低公分母的语言。
您回答中的开场白,关于更多的复杂性和微薄的收获,正是我在 6 年后的文章中详细阐述的内容:nayuki.io/page/unsigned-int-considered-harmful-for-java
@Nayuki 你的文章真的很好。只是一个小评论,我会使用加法 0x80000000 作为比较运算符而不是 XOR,因为它解释了它的工作原理,它将发生比较的连续区域从 -MAXINT 向上移动到 0。按位其效果完全相同。
N
Nayuki

我知道这篇文章太旧了;但是为了您的兴趣,在 Java 8 及更高版本中,您可以使用 int 数据类型来表示一个无符号的 32 位整数,它的最小值为 0,最大值为 232 -1。使用 Integer 类将 int 数据类型用作无符号整数,compareUnsigned()divideUnsigned() 等静态方法已添加到 Integer 类以支持无符号整数的算术运算。


J
John Hascall

使用 JDK8,它确实对它们有一些支持。

尽管 Gosling 担心,但我们可能会看到 Java 完全支持无符号类型。


又名“所以人们真的使用它,我们错了不包括它开始” - 但我们仍然不太相信 Java 开发人员知道变量是否已签名 - 所以我们不打算实现它们在 VM 中或作为与其签名表亲等效的类型。
R
Rob Ottaway

我听说它们将被包含在原始 Java 版本附近。 Oak 是 Java 的前身,在一些规范文档中提到了 usigned 值。不幸的是,这些从未进入 Java 语言。据任何人都能够弄清楚他们只是没有得到实施,可能是由于时间限制。


这很好......除了来自 Gosling 采访的证据暗示无符号整数(除了 char)被排除在外,因为设计者认为它们是一个坏主意......考虑到语言的目标。
如果手头有文件证据,最好不要过分重视目击者的陈述。
J
Jonathan

我曾经和 C++ 标准委员会的某个人一起上过 C++ 课程,他暗示 Java 做出了正确的决定来避免使用无符号整数,因为 (1) 大多数使用无符号整数的程序在使用有符号整数时也能做得很好,这在就人们的思维方式而言,以及 (2) 使用无符号整数会导致许多易于创建但难以调试的问题,例如整数算术溢出和在有符号和无符号类型之间转换时丢失重要位。如果你错误地使用有符号整数从 0 中减去 1,它通常会更快地导致你的程序崩溃,并且比如果它环绕到 2^32 - 1 更容易找到错误,并且编译器和静态分析工具和运行时检查必须假设您知道自己在做什么,因为您选择使用无符号算术。此外,像 -1 这样的负数通常可以表示一些有用的东西,比如一个被忽略/默认/取消设置的字段,而如果你使用 unsigned 你必须保留一个特殊的值,比如 2^32 - 1 或类似的东西。

很久以前,当内存有限且处理器不能一次自动在 64 位上运行时,每一位都更重要,因此有符号字节与无符号字节或短路实际上更重要,显然是正确的设计决策。今天,在几乎所有常规编程情况下,仅使用带符号的 int 就绰绰有余了,如果您的程序确实需要使用大于 2^31 - 1 的值,那么您通常只需要一个 long 值。一旦你进入了使用 long 的领域,就更难想出一个你真的无法使用 2^63 - 1 个正整数的原因。每当我们使用 128 位处理器时,问题就更小了。


佚名

您的问题是“为什么 Java 不支持无符号整数”?

我对你的问题的回答是 Java 希望它的所有原始类型:byte、char、short、int 和 long 应该分别被视为 byte、word、dword 和 qword,就像在汇编中一样,并且 Java 运算符是有符号的对除 char 之外的所有原始类型的操作,但仅在 char 上,它们仅是无符号的 16 位。

所以静态方法也假设是 32 位和 64 位的无符号操作。

您需要最终类,可以为无符号操作调用其静态方法。

您可以创建这个最终类,将其命名为您想要的任何名称并实现它的静态方法。

如果您不知道如何实现静态方法,那么此 link 可能会对您有所帮助。

在我看来,如果 Java 既不支持无符号类型也不支持运算符重载,Java 与 C++ 一点也不相似,所以我认为 Java 应该被视为与 C++ 和 C 完全不同的语言。

顺便说一句,语言的名称也完全不同。

所以我不建议在 Java 中键入类似于 C 的代码,我根本不建议键入类似于 C++ 的代码,因为那样在 Java 中你将无法在 C++ 中做你接下来想做的事情,即代码不会继续像 C++ 一样,对我来说,这样的代码是不好的,改变中间的样式。

我建议也为签名操作编写和使用静态方法,因此您不会在代码中看到用于签名和未签名操作的运算符和静态方法的混合,除非您只需要代码中的签名操作,并且可以仅使用运算符。

此外,我建议避免使用 short、int 和 long 原始类型,而分别使用 word、dword 和 qword,并且您要为无符号操作和/或有符号操作调用静态方法,而不是使用运算符。

如果您打算只进行有符号操作并且只在代码中使用运算符,那么可以使用这些原始类型 short、int 和 long。

实际上 word、dword 和 qword 在语言中不存在,但是您可以为每个创建新类,并且每个的实现应该非常容易:

类 word 仅包含原始类型 short,类 dword 仅包含原始类型 int,类 qword 仅包含原始类型 long。现在所有的无符号和有符号方法都是静态的或者不是你的选择,你可以在每个类中实现,即所有的 16 位操作都是无符号的和有符号的,通过在单词类上给出含义名称,所有的 32 位操作都是无符号的和通过在 dword 类上给出含义名称进行签名,所有 64 位操作都通过在 qword 类上给出含义名称来进行无符号和有符号操作。

如果您不喜欢为每个方法提供太多不同的名称,您总是可以在 Java 中使用重载,很高兴看到 Java 也没有删除它!

如果您想要方法而不是用于 8 位有符号操作的操作符和用于完全没有操作符的 8 位无符号操作的方法,那么您可以创建 Byte 类(请注意,第一个字母 'B' 是大写的,所以这不是原始类型字节)并实现此类中的方法。

关于值传递和引用传递:

如果我没记错的话,就像在 C# 中一样,原始对象自然是按值传递的,而类对象自然是按引用传递的,这意味着 Byte、word、dword 和 qword 类型的对象将按引用而不是按值传递默认。我希望 Java 有 C# 的 struct 对象,所以所有 Byte、word、dword 和 qword 都可以实现为 struct 而不是类,所以默认情况下它们是按值传递而不是按引用传递,就像 C# 中的任何 struct 对象一样和原始类型一样,默认情况下是按值传递而不是按引用传递,但是因为 Java 比 C# 差,我们必须处理它,所以只有类和接口,它们通过引用而不是按值传递默认。因此,如果您想通过值而不是通过引用传递 Byte、word、dword 和 qword 对象,就像 Java 和 C# 中的任何其他类对象一样,您将不得不简单地使用复制构造函数,仅此而已。

这是我能想到的唯一解决方案。我只是希望我可以将原始类型 typedef 到 word、dword 和 qword,但是 Java 既不支持 typedef 也不支持 using,这与支持 using 的 C# 不同,这相当于 C 的 typedef。

关于输出:

对于相同的位序列,您可以通过多种方式打印它们:二进制、十进制(如 C printf 中 %u 的含义)、八进制(如 C printf 中 %o 的含义)、十六进制(如C printf 中 %x 的含义)和整数(类似于 C printf 中 %d 的含义)。

请注意,C printf 不知道作为参数传递给函数的变量的类型,因此 printf 仅从传递给函数的第一个参数的 char* 对象中知道每个变量的类型。

所以在每个类中:Byte、word、dword 和 qword,您可以实现 print 方法并获得 printf 的功能,即使该类的原始类型是有符号的,您仍然可以通过遵循一些涉及的算法将其打印为无符号逻辑和移位操作以获取要打印到输出的数字。

不幸的是,我给您的链接没有显示如何实现这些打印方法,但我相信您可以通过谷歌搜索实现这些打印方法所需的算法。

这就是我能回答你的问题并建议你的全部内容。


MASM(Microsoft 汇编程序)和 Windows 将 BYTE、WORD、DWORD、QWORD 定义为无符号类型。对于 MASM,SBYTE、SWORD、SDWORD、SQWORD 是有符号类型。
M
Michael

因为 unsigned 类型是纯粹的邪恶。

在 C 中 unsigned - int 产生 unsigned 的事实更加邪恶。

这是不止一次让我着迷的问题的快照:

// We have odd positive number of rays, 
// consecutive ones at angle delta from each other.
assert( rays.size() > 0 && rays.size() % 2 == 1 );

// Get a set of ray at delta angle between them.
for( size_t n = 0; n < rays.size(); ++n )
{
    // Compute the angle between nth ray and the middle one.
    // The index of the middle one is (rays.size() - 1) / 2,
    // the rays are evenly spaced at angle delta, therefore
    // the magnitude of the angle between nth ray and the 
    // middle one is: 
    double angle = delta * fabs( n - (rays.size() - 1) / 2 ); 

    // Do something else ...
}

你注意到这个错误了吗?我承认我只是在使用调试器后才看到它。

因为 n 是无符号类型 size_t,所以整个表达式 n - (rays.size() - 1) / 2 的计算结果为 unsigned。该表达式旨在成为n中间光线的 有符号 位置:左侧中间光线的第一条光线的位置为 -1,第一条光线在左侧右边的位置 +1 等。在取 abs 值并乘以 delta 角度后,我将得到 n 光线和中间光线之间的角度。

对我来说不幸的是,上面的表达式包含邪恶的无符号,而不是评估为 -1,而是评估为 2^32-1。随后转换为 double 密封了该错误。

在因滥用 unsigned 算术而导致的一两个错误之后,人们不得不开始怀疑获得的额外位是否值得额外的麻烦。我正在尽可能地避免在算术中使用任何 unsigned 类型,尽管仍然将它用于非算术运算,例如二进制掩码。


向 Java 添加“unsigned long”会很尴尬。然而,添加更小的无符号类型应该没有问题。尤其是小于“int”的类型可以通过以数字明显的方式将它们提升为“int”来轻松处理,并且可以通过说涉及有符号整数和无符号整数的操作将提升“无符号整数”来处理两个操作数都为“long”。唯一的问题情况是涉及无符号长整数和有符号数量的操作,因为没有类型能够表示两个操作数的所有值。
@supercat:如果 unsigned 在每次操作中都转换为 int,那么 unsigned 有什么用?它没有任何与 short 不同的功能。而如果你只在混合操作上转换成int,例如unsigned+intunsigned+float,那么你仍然会遇到((unsigned)25-(unsigned)30)*1.0 > 0的问题,这是与unsigned相关的错误的主要原因。
许多对无符号类型的操作会升级为“long”。在将结果存储回无符号类型时要求显式转换会引起与 short 和 byte 相同的烦恼,但如果类型主要是存储格式而不是计算格式,那应该不是问题。在任何情况下,比“int”短的无符号类型应该能够毫无困难地提升为“int”。
我不喜欢这个答案,因为它使用了“无符号整数是邪恶的,不应该存在,因为它们永远不能被签名”的论点。任何试图从无符号整数中减去的人都应该知道这一点。至于可读性,C 语言并不以易于理解而著称。此外,(半)论点“额外的一点不值得额外的麻烦”也很弱。错误处理而不是 exit(1); 真的“值得额外的麻烦”吗?不能打开大文件真的值得缺乏经验的 Java 程序员使用 unsigned 不会搞砸的安全性吗?
我在这段代码中看到的唯一邪恶是 n - (rays.size() - 1) / 2。您应该始终将二元运算符括起来,因为代码的读者不需要对计算机程序中的操作顺序做出任何假设。仅仅因为我们通常说 a+bc = a+(bc) 并不意味着您可以在阅读代码时假设这一点。此外,计算应该在循环之外定义,以便可以在没有循环的情况下对其进行测试。这是一个错误,无法确保您的类型对齐,而不是无符号整数的问题。在 C 中,您可以确保您的类型对齐。
M
MKhomo

Java 出于务实的原因放弃了“C”规范中的一些宝石,但随着开发人员的需求(闭包等),它们正在慢慢回升。

我提到第一个是因为它与这个讨论有关;指针值对无符号整数算术的遵守。并且,关于这个线程主题,在 Java 的签名世界中维护无符号语义的困难。

我猜如果有人要让 Dennis Ritchie 改变自我来建议 Gosling 的设计团队,它会建议给 Signed 一个“无穷处为零”,这样所有地址偏移请求都会首先添加它们的 ALGEBRAIC RING SIZE 以避免负值。

这样,在数组中抛出的任何偏移量都不会生成 SEGFAULT。例如,在一个封装类中,我称之为需要无符号行为的双精度环数组 - 在“自旋转循环”上下文中:

// ...
// Housekeeping state variable
long entrycount;     // A sequence number
int cycle;           // Number of loops cycled
int size;            // Active size of the array because size<modulus during cycle 0
int modulus;         // Maximal size of the array

// Ring state variables
private int head;   // The 'head' of the Ring
private int tail;   // The ring iterator 'cursor'
// tail may get the current cursor position
// and head gets the old tail value
// there are other semantic variations possible

// The Array state variable
double [] darray;    // The array of doubles

// somewhere in constructor
public RingArray(int modulus) {
    super();
    this.modulus = modulus;
    tail =  head =  cycle = 0;
    darray = new double[modulus];
// ...
}
// ...
double getElementAt(int offset){
    return darray[(tail+modulus+offset%modulus)%modulus];
}
//  remember, the above is treating steady-state where size==modulus
// ...

上面的 RingArray 永远不会从负索引中“获取”,即使恶意请求者试图这样做。请记住,还有许多合法请求要求提供先前(负)索引值。

注意:外部 %modulus 取消引用合法请求,而内部 %modulus 从比 -modulus 更负面的负面中掩盖了公然的恶意。如果这曾经出现在 Java +..+9 || 8+..+ 规范,那么问题将真正成为“无法“自转”故障的程序员”。

我确信所谓的Java unsigned int '缺陷'可以用上面的单线来弥补。

PS:只是为了给上面的 RingArray 管家提供上下文,这里有一个候选的 'set' 操作来匹配上面的 'get' 元素操作:

void addElement(long entrycount,double value){ // to be called only by the keeper of entrycount
    this.entrycount= entrycount;
    cycle = (int)entrycount/modulus;
    if(cycle==0){                       // start-up is when the ring is being populated the first time around
        size = (int)entrycount;         // during start-up, size is less than modulus so use modulo size arithmetic
        tail = (int)entrycount%size;    //  during start-up
    }
    else {
        size = modulus;
        head = tail;
        tail = (int)entrycount%modulus; //  after start-up
    }
    darray[head] = value;               //  always overwrite old tail
}

什么“C规范”中有什么“闭包”?
对不起,我的速记太神秘了,我不幸的选择了例子。但是你是对的,作为内置的闭包是 C 的面向对象的后代。不是 C。C 允许那些关心的人构建他们自己的“闭包”,如果他们愿意的话,因为可以从任何上下文访问 C 程序函数和内存地址命名空间。我只是给出了一个“C”示例,说明如何可以控制对动态内存的恶意引用,其中符号可以是中性的并且始终是算术的,并且它的偏移量就像代数环一样。例如,总是以 sizeof 为模。
m
mike g

我能想到一个不幸的副作用。在 Java 嵌入式数据库中,32 位 id 字段可以拥有的 id 数量是 2^31,而不是 2^32(约 20 亿,而不是约 40 亿)。


他可能正在考虑数组并且不能使用负整数作为索引。大概。
当数据库中的自动增量字段溢出时,它们通常会变得古怪。
D
Denis Co

恕我直言的原因是因为他们/太懒惰而无法实施/纠正该错误。建议 C/C++ 程序员不懂无符号、结构、联合、位标志……简直是荒谬。

以太您正在与即将开始编写 la C 语言的基本/bash/java 程序员交谈,没有任何真正的语言知识,或者您只是在胡说八道。 ;)

当您每天处理来自文件或硬件的格式时,您开始质疑,他们到底在想什么。

一个很好的例子是尝试使用无符号字节作为自旋转循环。对于那些不理解最后一句话的人,你到底是如何称自己为程序员的。

直流


只是为了好玩,谷歌“自旋转循环”这个短语。显然,Denis Co 是世界上唯一一个值得称自己为程序员的人 :-)
这个答案太糟糕了,这很有趣