在哪种情况下,'uint'和'short'数据类型比标准int(32)更合适?


24

我了解它们可以代表的能力和价值观的差异,但似乎人们总是在使用Int32,无论它是否合适。似乎没有人使用无符号版本(uint),尽管很多时候它更适合使用,因为它描述的值不能为负(也许代表数据库记录的ID)。同样,似乎没有人使用short/Int16该值所需的容量。

客观地说,在那里的情况下最好是使用uintshort/Int16如果是这样,这是他们?


13
流行度并非始终是评估软件设计决策的可行指标。仅仅因为一种习惯很流行并不意味着它是适合您特定应用的适当实践,也不意味着它甚至是一种好的实践。
罗伯特·哈维2014年


1
我认为,简短的答案是,程序员已经习惯了带符号的语义,即使在处理无符号类型(因此也就是无符号的语义)时,也倾向于采用那些。大多数人认为这是程序员懒惰或没有受过教育的问题,但是实际上,有问题的程序员可能受过良好的教育,非常谨慎,并希望避免细微的陷阱。如果愿意,请看一下soundsoftware.ac.uk/c-pitfall-unsignedanteru.net/2010/05/17/736
Theodoros Chatzigiannakis 2014年

在无符号数字中,符号null大于正号或负号。如果您认为它永远不会是消极的或永远是积极的,那么您会对结果感到惊讶(并且经常会生气),因为它实际上并没有那么有效,特别是当与/相减时/从带符号的值。
亚当·鲁珀

1
以我的经验,曾经使用C语言编程的许多程序员都倾向于关心GB的内存和存储空间的字节数。
user1451111

Answers:


25

我怀疑您所指的是一种根据您自己的经历而变色的观点,即您没有与正确使用整数类型的人一起工作。这可能很常见,但是根据我的经验,人们通常也会正确使用它们。

好处是内存空间和cpu时间,可能还有IO空间,具体取决于类型是通过有线还是磁盘发送。无符号类型为您提供了编译器检查,以确保您不会执行某些不可能的操作,并在保留可能的范围的同时扩大可用范围,同时在可能需要的情况下保持较小的大小以提高性能。

正确使用是你所期望的-任何时候,你知道肯定你可以用它们永久地(不限制不确定性,或者你后悔就晚了)。

  • 如果您要表示的东西永远不可能是负数(public uint NumberOfPeople),请使用无符号类型。
  • 如果您要表示的东西不可能合理地大于255(public byte DamagedToothCount),请使用一个字节。
  • 如果您要表示的东西可以合理地大于255,但绝不能表示成千上万,请使用短(public short JimmyHoffasBankBalance)。
  • 如果您要表示的东西可能成千上万,甚至数百万,但不可能达到数十亿,请使用int(public int HoursSinceUnixEpoch)。
  • 如果您可以肯定地知道这个数字可能具有无限大的价值,或者您认为它可能有数十亿美元,但不确定多少亿美元,那么最好的选择就是长久。如果long不够大,那么您会遇到一个有趣的问题,需要开始查看任意精度的数字(public long MyReallyGreatAppsUserCountThisIsNotWishfulThinkingAtAll)。

可以在整个有符号,无符号和各种大小的类型之间进行选择时使用这种推理,只需考虑一下现实中要表示的数据的逻辑真相即可。


11
+1,尽管我必须明确指出电话“数字”不是数字,而是数字字符串和可选的格式。您似乎已经意识到了这一点,但是我们不想树立一个不好的榜样,现在可以了吗?此外,任意限制某个值的范围是一种短视的反模式- int到处都是,除非您知道问题域实际上限制了该值的事实-没有银行会想将帐户硬限制为33K quid(并考虑到乐趣)当那溢出...!)。
阿蒙2014年

3
新生活目标:大量透支使我的银行帐户的整体类型下溢。
recursion.ninja 2014年

11
有充分的理由不在某些地方使用无符号类型,例如,在有符号和无符号之间混合使用算术时。请参阅有关无符号整数的最佳做法是什么?

19
我不同意这里的推理。无符号类型通常是一个错误,因为如果习惯使用整数,则减法和比较是意外的(它们以一致的方式工作,但不是“总是肯定的”)。除非您有非常特定的理由使用它们,否则我将避免使用它们。另外,为什么大小对于byte vs short与int很重要?您通常甚至不节省空间,因为结构会将这些成员或数组填充到一定的对齐方式。仅当大小确实很重要(不太可能出现在我所见的C#代码中)或您特别想在255处进行环绕操作时,才使用字节。
亚当·鲁珀

4
“好处是内存空间和cpu时间” ...我看不到任何小类型实际上可以节省CPU时间的情况。整数运算永远不会比机器大小的运算更快,也就是说,就CPU而言,您最好还是使用long。当然,节省内存可以通过提高高速缓存行效率等间接地节省时间,但是OTOH与小类型的对齐问题会间接地浪费时间。
大约

16

当然,在某些情况下,最好使用uintor short或or Int16。当您知道数据范围将适合该变量类型的约束时,则可以使用该类型。

在内存受限的环境中或处理大量对象时,使用最小大小的变量可能很有意义。例如,ints与shorts的一百万个元素数组在大小上存在显着差异。

通常,由于以下一种或多种原因,在实际代码中不会发生这种情况:

  • 数据约束事先未知
  • 数据约束可能不牢固或已知可能会更改
  • 希望可以在更大的数据范围内重新使用该功能
  • 开发人员没有花时间思考约束
  • 使用较小的变量类型来节省内存是微不足道的

还有更多可能的原因,但归结为: 决定和使用其他变量类型所花费的时间并没有提供足够的好处来证明这样做的合理性。


8

在C语言中,在不涉及整数提升的情况下,将无符号值指定为充当“包装”抽象代数环的成员(因此,对于任何X和Y,XY将产生一个唯一值,当将其添加到Y时,它将产生X ),而有符号整数类型在计算保持在一定范围内时被指定为表现为整数,并且在计算超出该范围时可以执行任何操作。但是,C#中的数字语义完全不同。在检查的数值上下文中,有符号和无符号类型的行为都类似于整数,只要计算在范围内即可,而OverflowException在不处于计算范围时则抛出该整数。在不受约束的上下文中,它们的行为都像代数环。

通常,只有Int32在需要打包或拆包东西以进行紧凑的存储或运输时,才值得使用小于任何数据类型的唯一值。如果一个人需要存储十亿个正数,并且它们都在0到100的范围内,则每个使用一个字节而不是四个字节可以节省1.5 GB的存储空间。那是一大笔钱。但是,如果一段代码总共需要存储数百个值,则将每个值设为一个字节而不是四个字节将节省大约600个字节。可能不值得打扰。

对于无符号类型,只有在执行信息交换或将数字细分时才真正有用。例如,如果需要对96位整数进行数学运算,则对三个无符号32位整数的组进行计算可能比对带符号整数组进行计算要容易得多。否则,在大多数情况下,有符号的32位或64位值的范围将不足,但是相同大小的无符号值就足够了。


4

使用无符号类型通常是一个坏主意,因为它们以不愉快的方式溢出。x = 5-6在您的代码中突然变成了定时炸弹。同时,无符号类型的好处可以归结为一点点的精度,如果这一点对您来说值得,那么几乎应该肯定会使用更大的类型。

在某些情况下,较小的类型可能有意义,但除非您担心内存使用情况或需要打包数据以提高传输或缓存效率或其他一些问题,否则通常情况下使用较小的类型没有任何好处。而且,在许多体系结构上,使用这些类型实际上要慢一些,因此它们实际上可以带来很小的成本。


3
在C语言中,有符号的溢出甚至比无符号的溢出更糟糕(因为它是未定义的行为,而指定的无符号就像里程表一样翻转)。OTOH,签名上溢/下溢在实践中要比未签名下溢少得多。
凯文(Kevin)

的确如此,但有符号的溢出通常更明显且可预测。
杰克·艾德利2014年

我大体上同意,但你必须要注意,例如,现代的编译器可以优化i+1>i1,如果i签署,与其他令人讨厌的行为一大堆一起。无符号的溢出会在极端情况下导致错误。带符号的溢出会使您的整个程序变得毫无意义
凯文(Kevin)

@JackAidley我很确定您说的没有任何意义,因为5-6会产生相同的位模式,无论它是否未签名。
Ingo 2014年

@Ingo:您多久查看一次位模式?重要的是位模式的含义,而不是打开或关闭哪些位。
杰克·艾德利2014年

2

当专门处理.NET类型时,CLS Compliance经常被遗忘并且可能与您的问题相切。并非所有类型都适用于.NET Framework上构建的所有语言。

如果您正在编写要由C#以外的语言使用的代码,并且希望确保该代码能够与尽可能多的.NET语言进行互操作,则必须将类型用法限制为与CLS兼容的语言。

例如,VB.NET的早期版本(7.0和7.1)不支持无符号整数(UInteger):

http://msdn.microsoft.com/zh-CN/library/aa903459(v=vs.71).aspx

无符号整数不符合CLS,因此如果不确定谁是类库使用者,应谨慎使用。

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.