我在mac Mavericks上使用fpc 2.6.2和Lazarus 1.0.12 我创建了一个像这样的变量
var
MyVar : 7..200;
如果我在MyVar
的子范围之外为7..200
分配值,编译器仍会接受最多255的值。如果我分配256,则MyVar
中的值变为{{ 1}}如果我分配0
,则257
变为1,依此类推。有人知道发生了什么事吗?
答案 0 :(得分:3)
您尚未创建子范围。 :-)你已经声明了一个变量(使用var
)。要正确创建子范围,首先要声明type
:
type
TMyRange = 7..200;
然后,您将变量声明为type
:
var
MyVar: TMyRange;
尝试分配超出该范围的值会导致编译器错误(例如,在带有范围检查的Delphi中):
MyVar := 201;
[dcc32错误] Project1.dpr(22):E1012常量表达式违反了子范围
启用范围检查通常是一个非常好的主意,这样编译器就能为您工作。 (打开溢出检查通常也是一个好主意,至少在开发过程中是这样。看看这个答案的其余部分是为了什么。)
就您所看到的行为而言,编译器将创建将保存子范围的最小尺寸序数类型(在本例中为Byte
)。在这种情况下,您尚未声明一个子范围,而是一个简单的变量,编译器适合byte
。
由于一个字节可以保存来自0..255
的值,并且您已声明了一个字节变量,因此它可以容纳的最大值为255.如果您指定256(并且未在编译器中打开溢出检查)选项),值溢出并回绕到最小值(零)+ 1(溢出的位数)。将257
换行分配到最小值+ 2(再次,它溢出的量)。
答案 1 :(得分:1)
我相信FreePascal实际上创建了一个字节类型变量(因为它是包含给定范围的最小类型),它接受值0..255。数字256需要二进制的两个字节1和0(0000 0001 0000 0000)。分配给MyVar的最低得分。如果打开溢出检查,程序将引发异常而不是静默切割值。您可以通过-Co
编译器参数或在源代码中使用{$Q-}
和{$Q+}
编译器指令来执行此操作。
对于分配低于7或高于200的值,您可以通过使用命令行选项-Cr
打开范围检查来避免这种情况。在源代码中,您还可以使用{$R-}
和{$R+}
指令分别关闭和打开范围检查。
我建议在开发过程中始终打开溢出和范围检查。它确实有一些性能损失,因此如果它开始损害性能,你可以在发布时关闭它。