Ast*_*oth 17 delphi pascal freepascal
我不是Pascal新手,但直到现在我仍然不知道为什么Delphi和Free Pascal通常声明参数并将值返回为有符号整数,而我看到它们应该始终是正数.例如:
Pos()返回Integer的类型.有可能成为负面的吗?SetLength()将NewLength参数声明为Integer的类型.字符串是否有负长度?System.THandle宣称为Longint.手柄有负数吗?有许多决定,如Delphi和Free Pascal.这背后有什么考虑因素?
Mar*_*ort 16
在Pascal中,Integer(signed)是基类型.所有其他整数类型都是整数的子范围.(这在Borland方言中并不完全正确,考虑到TP中的longint和Delphi中的int64,但足够接近).
如果计算的中间结果为负,并且使用无符号整数计算,则会触发范围检查错误的一个重要原因,并且由于大多数较旧的编程语言不假设2 - 补码整数,结果(范围检查关闭)甚至可能是腐败的.
THandle案例要简单得多.Delphi没有正确的32位无符号直到D4,但只有31位基数.(因为32位无符号整数不是整数的子范围,后面的无符号整数是int64的子集,它将问题移到uint64,这只是在D2010中添加的左右)
所以在头文件的许多地方都使用了签名类型,其中winapi使用无符号类型,可能是为了避免第32位在这些版本中被破坏,并且自定义卡住了.
但是,winapi案例与一般情况不同.
稍后添加一些Pascal(和Modula2/3)实现通过将整数设置为大于wordsize的大小来绕过此陷阱,并且需要所有数字类型来声明适当的子范围,如下面的程序中所示.
第一个假设主要假设一切都是整数的子集,第二个允许编译器再次将所有内容再次缩小以适应寄存器,特别是如果CPU具有大于字操作的某些操作.(如x86,其中32位*32位mul给出64位结果,或者可以使用状态位检测字大小溢出(例如,为添加生成范围异常而不进行完整的2*字大小添加)
   var x : 0..20;
       y : -10..10;
   begin
     // any expression of x and y has a range -10..20
Dav*_*nan 13
好吧,因为一个开始THandle声明不正确.它在Windows标头中是未签名的,在Delphi中应该是这样.事实上,我认为这在最近的Delphi版本中得到了纠正.
我认为签署无签名的偏好主要是历史性的,并不是特别重要.但是,我可以想到一个重要的例子.考虑for循环:
for i := 0 to Count-1 do
如果i是无符号且Count为0,则此循环从0运行到$FFFFFFFF不是您想要的.使用带符号的整数循环变量可以避免该问题.
Pascal是这里语法的受害者.等效的C或C++循环没有这样的麻烦
for (unsigned int i=0; i<Count; i++)
由于句法差异和使用比较运算符作为停止条件.
这也可能Length()是字符串或动态数组返回有符号值的原因.因此,为了保持一致性,SetLength()应接受签名值.并且假设返回值Pos()用于索引字符串,它也应该被签名.
这是关于该主题的另一个Stack Overflow讨论:我应该使用无符号整数来计算成员吗?
当然,我在这里疯狂地猜测.也许没有设计,只是出于习惯,使用有符号值的先例已经确定并且已经成为现实.
War*_* P 6
使用有符号整数的原因有很多,甚至有些原因可能适用于您不打算返回负值的情况.
想象一下,我编写了调用Pos的代码,我想对结果进行数学运算.你是否宁愿有一个负面结果(Pos('x',s)-5)提出范围检查异常,下溢并成为一个非常大的无符号数约40亿,或者如果Pos('x',s)返回则变为负数1?对于很少考虑这些案例的新用户来说,任何一个都是问题的根源,但是长期以来的传统是通过使用Integer结果,检查负结果和零结果并且不将它们用作字符串偏移是你的工作.对于初级和高级程序员来说,使用Integer并且没有"负"值滚动并成为大的无符号值或提高范围异常是有利的.
其次,请记住,在开始编程时,通常会Integer在引入无符号类型之前引入(签名)类型Cardinal.初学者经常使用类似的函数Pos,并且使用将创建最不友好的副作用的类型是有意义的.如果范围大于您绝对需要的范围,则没有负面的副作用(Pos可能需要的范围是1到最大字符串长度在delphi中).使用CardinalPos 的类型在32位Delphi中没有任何好处,选择它肯定有缺点.
但是,一旦你进入64位delphi,理论上你可以拥有比Integer更大的字符串,并且转移到Cardinal不会解决你所有潜在的问题.但是,任何人拥有2 GB以上字符串的可能性都是零,而Delphi 64位编译器不允许使用>2 GB字符串.在我的测试中,我可以在64位Delphi中实现近1 GB的字符串.因此,Win64字符串的实际长度限制大约是十亿(1073741814)个字符,这使用了近2 GB的实际RAM.在那个限制,我得到EIntOverflow或EAccessViolation,似乎我打击德尔福运行时库(RTL)错误,没有正确定义限制,所以你的里程可能会有所不同.