Java为什么不支持unsigned ints?


374

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

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

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

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

包括这些的不利之处是什么?


137
我不知道,但它使我烦恼。例如,以这种方式编写网络代码要困难得多。
Tamas Czinege 09年

20
我希望有只有两个语言/数据库/ ...世界类型:数字和字符串:)

5
编写网络代码一点也不难。BTW InputStream.read(),返回一个无符号字节,例如不是一个有符号字节,因此网络示例是混乱的恕我直言。唯一令人困惑的是,您假设写一个有符号的值与写一个无符号的值有什么不同。即,如果您实际上不知道字节级别发生了什么。
彼得·劳瑞

19
@ZachSaw-当我看到语言设计师对此报价时,我也做了两遍。没有什么比无符号整数更简单了。有符号整数很复杂。尤其是当您考虑在晶体管级别旋转时。有符号整数如何移位?我不得不得出结论,Java的设计者在理解布尔逻辑时遇到了一个严重的问题。
PP。

8
对我来说,进行任何图像处理都变得越来越困难,因为图像byte不能给出纯正的140灰度级,而是-116需要& 0xff获得正确的值。
Matthieu 2014年

Answers:


193

这是来自对Gosling和其他人的关于简单性的采访

高斯林:对于我作为语言设计师来说,这几天我并不算是真正的自己,“简单”最终的含义是我可以期望J. Random Developer掌握该规范。该定义表明,例如,Java并非如此-实际上,其中许多语言最终都带有很多极端情况,这是没人真正理解的。询问任何C开发人员有关无符号的知识,很快您就会发现几乎没有C开发人员真正了解无符号的含义,无符号的算法是什么。这样的事情使C变得复杂。我认为Java的语言部分非常简单。您必须查找的库。


222
我将在这里举一个具体的例子来反对高斯林(至少来自CLR)。给一个数组一个带符号的整数长度值或一个无符号的长度还有什么更令人困惑?数组的长度不可能为负数,但我们的API指出这是可能的。
JaredPar

18
使Java变得简单的观点是使我们陷入混乱的原因之一,因为缺少模板,最终模板将它们带入了语言中,因为这些选择非常繁琐。我确实认为,尽管可以使用适当的类来支持unsigned int,但它不需要素数
Uri 2009年

59
如果Java由于数组索引不能为负数而需要无符号整数,则它也需要子范围(大约为Pascal),因为数组索引不能大于数组大小。
韦恩·康拉德

81
好的,他只是告诉了没有无符号类型的优点。现在,让我们来计算一下不利之处……
Moshe Revah 2010年

83
我更喜欢代码简单而不是语言简单。这就是为什么我讨厌Java。
Pijusn 2012年

50

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

  • 通常,Java设计人员希望简化可用数据类型的清单
  • 对于日常用途,他们认为最常见的需求是签名数据类型
  • 为了实现某些算法,有时需要使用无符号算术,但是将要实现这种算法的那种程序员也将具有“工作”的能力,以对带符号数据类型进行无符号算术

通常,我会说这是一个合理的决定。可能,我会:

  • 将字节设置为无符号,或者至少为该数据类型提供了一个有符号/无符号的替代名称(可能具有不同的名称)(将其签名有利于一致性,但是什么时候需要一个有符号字节?)
  • 删除了“短”(您上次使用16位带符号算术的时间?)

尽管如此,通过一点点合并,对不超过32位的无符号值的操作也不错,而且大多数人不需要进行无符号的64位除法或比较。


2
我也想拥有无符号字节,但是我怀疑整数类型之间完全一致的优势远胜于无符号字节带来的便利。
艾伦·摩尔

64
“对于日常用途,他们认为最常见的需求是签名数据类型”。在我的C ++代码中,我经常会想到:“为什么我在这里使用有符号整数而不是无符号整数?!”。我觉得“有符号”是例外而不是规则(当然,这取决于域,但是正整数被称为自然数;- 是有原因的))。
Luc Touraille

15
大拇指要求无符号字节,在进行图像处理时,假设字节是无符号的(应该如此),这使我花费了数小时进行调试。
Helin Wang 2012年

7
您会惊讶地发现short它的使用频率-defltate / gzip / inflate算法为16位,并且它们严重依赖于短裤...或者至少short[][诚然,它们是本机的-但是该算法的java impl携带terrabytes的数据]。后者(short[])具有显着的优势,int[]因为它占用的内存减少了两倍,而内存减少了=更好的缓存属性,性能大大提高。
bestsss 2012年

8
尽管在特定的应用程序中,您应该衡量使用短裤是否能为您提供更好的性能,而不是假设它是正确的。操作短裤而不是整数(通常是处理器“喜欢使用”的类型)所需的额外的麻烦扑克实际上有可能实际上损害了特定应用程序的性能。并非总是如此,但您应该测试而不是假设。
尼尔·科菲

19

这是一个比较老的问题,帕特确实提到了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,有新的API LongInteger它们在将longint值视为无符号值时提供了辅助方法。

  • compareUnsigned
  • divideUnsigned
  • parseUnsignedInt
  • parseUnsignedLong
  • remainderUnsigned
  • toUnsignedLong
  • toUnsignedString

此外,Guava提供了许多辅助方法来对整数类型执行类似的操作,这有助于弥补由于缺乏对unsigned整数的本机支持而留下的空白。


2
但是,例如,char它太小而无法支持long算术。

3
这可能是Java的缺点

希望它们支持字节的无符号值。使事情变得更容易。
mixz

15

Java确实有无符号类型,或者至少有一种:char是无符号的short。因此,不管高斯林抛出什么借口,实际上就是他的无知,为什么没有其他未签名的类型。

还有短裤类型:短裤一直用于多媒体。原因是您可以在一个32位无符号长中容纳2个样本,并对多个操作进行向量化。8位数据和无符号字节相同。您可以将4或8个样本放入寄存器中进行矢量化。


37
是的,我敢肯定,与您相比,Gosling对Java非常无知。
jakeboxer 2009年

Java是否允许直接对无符号字节数量执行算术运算,或者总是将值提升?拥有一个无符号类型用于存储,但是总是对一个足够大的有符号类型进行算术运算就可以在语义上很好地解决问题,但是会导致对与“普通”整数大小相同的无符号类型进行操作会更加昂贵。
超级猫

2
char除字符外,其他任何样式都不好用。
starblue

5
@starblue当然是,但它是一个黑客绕过语言的限制
基本

14

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


12
关于混合有符号/无符号:您可以有无符号类型,但不允许混合(或要求显式强制转换)。不过,不清楚是否有必要。
sleske

2
在C ++中,您必须在static_cast周围撒很多s来混合它们。确实是一团糟。
Raedwald,时间

4
第八位在那里,它只是试图将自己隐藏为符号。
starblue 2012年

32位或更大的类型只会使事情变得混乱。我认为没有理由不应该byte像在Pascal中那样对Java 进行签名。
supercat 2014年

12
当您在Java中遇到图像处理问题时,请来找我,您希望字节是无符号的。然后您会知道,& 0xFF每次字节到整数的提升都会使代码更加混乱。
bit2shift

12

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

这个家伙说,因为C标准将涉及无符号和有符号的int的操作定义为无符号的。这可能会导致带负号的整数转为一个大的无符号int,从而可能导致错误。


34
Java带符号的整数也会四处滚动。我不明白你的意思。
foo

8
@foo:有符号整数必须变大才能引起问题。相比之下,在C语言中,将任何负整数-甚至- -1与任何无符号量-甚至零进行比较都会遇到问题。
超级猫

太糟糕了,Java不能包含无符号类型,但是具有有限的一组转换和混合运算符(有点类似于在C中可以将5加到一个指针,但是不能将一个指针与5进行比较的方式) 。在隐式转换存在时对混合类型使用运算符的想法应强制隐式使用该转换(并使用结果类型作为结果类型)是.NET和.NET中许多可疑设计决策的核心。 Java。
2013年

4
不必大惊小怪,而是-1“未知”年龄(如文章所示)是“代码气味”经典示例之一。例如,如果您要计算“爱丽丝比鲍勃大多少岁?”,并且A = 25和B = -1,您将得到答案,±26那是完全错误的。对未知值的正确处理是Option<TArg>何时Some(25) - None返回的某种方式None
2014年

11

我认为Java很好,添加unsigned会使它变得复杂,而没有太多收益。即使使用简化的整数模型,大多数Java程序员也不知道基本数字类型的行为-只需阅读《Java Puzzlers》一书,看看您可能会遇到什么误解。

至于实用建议:

  • 如果您的值是任意大小且不合适int,请使用long。如果它们不适合long使用BigInteger

  • 需要节省空间时,仅将较小的类型用于数组。

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

又见这个回答有关“移植一个随机数发生器从C到Java的”。


5
是的,对于右移你之间进行选择>>,并>>>分别签署和无符号。向左移动没有问题。
starblue 2011年

1
@starblue实际上>>>不适用于shortbyte。例如,(byte)0xff>>>1收益0x7fffffff而不是0x7f。另一个示例:byte b=(byte)0xff; b>>>=1;将产生b==(byte)0xff。当然可以,b=(byte)(b & 0xff >> 1);但这又增加了一个操作(按位&)。
CITBL

7
“ ...即使使用简化的模型,大多数Java程序员也不知道基本数字类型的行为...”我的某些想法只是讨厌针对最低公分母的语言。
基本

您的答案的开头,是关于更多的并发症和很少的收获,正是我6年后在我的文章中阐述的内容:nayuki.io/page/unsigned-int-considered-harmful-for-java
Nayuki 2016年

1
@Nayuki您的文章非常好。仅作一点说明,我将为比较运算符使用0x80000000而不是XOR,因为它解释了它为什么起作用,它将比较发生的连续区域从-MAXINT上移到0。按位,其效果完全相同。
starblue

6

有了JDK8,它确实为它们提供了一些支持。

尽管有Gosling的担忧,我们可能仍会看到Java中对无符号类型的完全支持。


12
又名“所以人们真的确实使用过它,我们错了,不包括它开头”-但我们仍然不太相信Java开发人员知道变量是否已签名-因此我们不会实现它们在VM中或作为与其签名表亲等效的类型。
基本

6

我知道这个帖子太旧了;但是,出于您的兴趣,在Java 8和更高版本中,可以使用int数据类型表示无符号32位整数,其最小值为0,最大值为2 32 -1。使用Integer类使用int的数据类型为无符号整数和静态方法一样compareUnsigned()divideUnsigned()等已经加入到Integer类,以支持算术运算的无符号整数。


4

我听说过一些故事,它们将被包含在原始Java版本的附近。Oak是Java的先驱,在某些规范文档中提到了未赋值。不幸的是,这些方法从未使它成为Java语言。据任何人都能够弄清楚,他们只是没有实施,可能是由于时间限制。


这样做很好...除了来自Gosling采访的证据表明未签名的整数(除之外char)被忽略了,因为设计师认为这是个坏主意...鉴于该语言的目标。
Stephen C

如果也有书面证据,最好不要在目击者的陈述中过分重视。
user7610

4

我曾经与C ++标准委员会的某人一起上过C ++课程,他暗示Java做出了避免使用无符号整数的正确决定,因为(1)大多数使用无符号整数的程序都可以对有符号整数做同样的事情,这在自然情况下更为自然。人们的想法,以及(2)使用无符号整数会导致很多容易创建但难以调试的问题,例如整数有符号溢出和在有符号和无符号类型之间进行转换时会丢失大量位。如果您错误地使用带符号整数从0中减去1,则通常比包裹到2 ^ 32-1更快,它会使程序崩溃并更容易发现错误,并且编译器和静态分析工具以及运行时检查必须假设您选择使用无符号算术,就知道自己在做什么。也,

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


2

您的问题是“为什么Java不支持unsigned ints”?

我对您的问题的回答是Java希望将其所有原始类型:bytecharshortintlong分别对待为byteworddwordqword,就像在汇编中一样,并且对Java操作符进行签名char以外,对所有其原始类型进行的操作,但仅在char上,它们仅是无符号的16位。

因此,静态方法假定对于32位和64位也是无符号操作。

您需要最终类,可以为未签名操作调用其静态方法。

您可以创建该最终类,将其命名为所需的任何名称,并实现它的静态方法。

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

在我看来,Java是不是类似于C ++ 在所有的,如果它既不支持无符号的类型,也不运算符重载,所以我认为Java应该从C ++和C.从完全不同的语言来处理

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

因此,我不建议在Java中键入类似于C的代码,也不建议完全键入与C ++类似的代码,因为那样的话,在Java中,您将无法使用C ++做下一步的工作,即代码根本不会继续像C ++一样,对我来说,这样修改中间的样式是不好的。

我建议也为签名操作编写和使用静态方法,因此除非在代码中只需要签名操作,否则就不要在运算符和静态方法的代码混合中看到带符号和无符号操作。仅使用运算符。

另外,我建议避免使用shortintlong基本类型,而分别使用worddwordqword,并且您将为未签名操作和/或已签名操作调用静态方法,而不是使用运算符。

如果只打算执行带符号的操作,并且仅在代码中使用运算符,则可以使用这些基本类型shortintlong

事实上双字四字没有在语言存在,但你可以为每个创建新类以及各自的实施应该是很容易的:

仅保留原始类型为short,类dword仅保留原始类型为int,而qword类仅保留原始类型为long。现在所有未签名和已签名方法都是静态的还是不是您选择的,您可以在每个类中实现,即,通过在单词类上给出含义名称来实现所有16位操作(无符号和有符号),所有32位操作(无符号和无符号)通过在dword类上给出含义名称来进行签名,而所有64位操作都可以通过在qword类上给出含义名称来进行无符号化和签名。

如果您不喜欢为每个方法提供太多不同的名称,则可以随时在Java中使用重载,这很不错,因为Java并没有将其删除!

如果要使用8位有符号运算的方法而不是运算符,而根本不需要运算符的8位无符号运算的方法,则可以创建Byte类(请注意,第一个字母'B'是大写字母,因此不是基本类型byte)并实现此类中的方法。

关于按值传递和按引用传递:

如果我没看错,就像在C#中一样,原始对象自然通过值传递,而类对象自然通过引用传递,这意味着Byteworddwordqword类型的对象将通过引用而不是通过值传递默认。我希望Java具有C#一样的struct对象,因此所有Byteworddwordqword都可以实现为struct而不是class,因此默认情况下它们是通过值传递的,而不是默认引用的,就像C#中的任何struct对象一样,例如原始类型,都是通过值传递的,而不是默认引用的,但是因为Java比C#差,所以为了解决这个问题,那么只有类和接口是通过引用传递的,默认情况下不是通过值传递的。因此,如果您想按值而不是按引用传递Byteworddwordqword对象,就像Java和C#中的任何其他类对象一样,您将只需要使用复制构造函数即可。

那是我能想到的唯一解决方案。我只希望我可以将基本类型的typedef定义为word,dword和qword,但是Java既不支持typedef也不使用,与C#一样,它支持using,它等效于C的typedef。

关于输出:

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

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

因此,在每个类中:Byteworddwordqword,您可以实现print方法并获得printf的功能,即使该类的原始类型是带符号的,您仍然可以通过遵循一些涉及以下算法的方法将其打印为unsigned:逻辑和移位运算,以获取要输出到输出的数字。

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

以上就是我可以回答您的问题并提出建议的地方。


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

1

因为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角度I,我将得到n射线与中间射线之间的角度。

对我来说不幸的是,上面的表达式包含邪恶的未签名,而不是计算为-1,而是计算为2 ^ 32-1。随后转换为double密封该错误。

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


在Java中添加“ unsigned long”会很尴尬。但是,添加较小的无符号类型应该没有问题。尤其是小于“ int”的类型可以很容易地通过将它们以数值上明显的方式提升为“ int”来处理,而“ unsigned int”可以通过处理涉及有符号int和无符号int的操作来提升。两个操作数都为“ long”。唯一的问题情况是涉及无符号长整型和有符号数的运算,因为没有类型能够表示两个操作数的所有值。
超级猫

@supercat:如果在每次操作时unsigned都转换为int,则有什么用unsigned?它没有与可以区别的任何功能short。而且,如果int仅转换为混合运算(例如unsigned+int或)unsigned+float,则仍然会遇到的问题((unsigned)25-(unsigned)30)*1.0 > 0,这是导致unsigned相关Bug的主要原因。
迈克尔

对无符号类型的许多操作将提升为“长整型”。将结果存储回无符号类型时需要显式强制转换会引起与short和byte存在的烦恼相同的烦恼,但是如果类型主要是存储格式而不是计算格式,那应该不成问题。在任何情况下,比“ int”短的无符号类型应该能够轻松升级为“ int”。
超级猫

3
我不喜欢这个答案,因为它使用了“无符号整数是邪恶的,不应该存在,因为它们永远都不会被签名”。任何试图从无符号整数中减去的人都应该已经知道这一点。至于可读性,并不容易理解C。此外,(半)论点“额外的位不值得额外的麻烦”也很弱。错误处理不是exit(1);真的“值得额外的麻烦”吗?能够打开大文件真的不值得经验不足的Java程序员不会搞乱的安全性unsigned吗?
yyny

2
我在这段代码中看到的唯一邪恶的东西是 n - (rays.size() - 1) / 2。您应该始终将二进制运算符括起来,因为代码的阅读者不需要假设任何有关计算机程序中操作顺序的内容。仅仅因为我们通常说a + b c = a +(b c)并不意味着您在阅读代码时就可以假设这一点。此外,应在循环外部定义计算,以便可以在不存在循环的情况下对其进行测试。这是一个不能确保您的类型对齐而不是无符号整数问题的错误。在C语言中,要确保您的类型对齐。
德米特里

0

Java出于实用性原因而放弃了“ C”规范中的一些瑰宝,但随着开发人员的需求(关闭等)而逐渐回落。

我提到第一个,因为它与本次讨论有关。指针值是否符合无符号整数算法。并且,相对于该线程主题,在Java的Signed世界中维护Unsigned语义存在困难。

我想如果要让Dennis Ritchie改变自我来建议Gosling的设计团队,那会建议给Signed一个“无穷大的零”,这样所有地址偏移量请求都将首先添加其ALGEBRAIC RING SIZE来消除负值。

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

// ...
// 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 + .. +规格,那么问题就真正地变成了“无法“自转” FAULT的程序员”。

我敢肯定,上述的单行代码可以弥补所谓的Java unsigned int'缺陷'。

PS:只是为了给上面的RingArray整理提供上下文,这是一个与上面的“ 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
}

-2

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


1
他可能正在考虑数组,而无法使用负整数作为索引。大概。
SK9

2
当数据库中的自动增量字段溢出时,它们通常会变得怪异。
约书亚

-8

恕我直言的原因是因为他们太懒了,无法实施/纠正该错误。暗示C / C ++程序员不了解无符号,结构,联合,位标记...只是荒谬。

以前,您正在与一位基础/ bash / java程序员交谈,即将开始对la C进行编程,而对此语言没有任何真正的了解,或者您只是出于自己的想法。;)

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

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

直流电


34
只是为了踢,谷歌短语“自我旋转循环”。 显然,Denis Co是世界上唯一值得称自己为程序员的人:-)
Stephen C

6
这个答案太糟糕了以至于很有趣
Nayuki 2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.