Reputation: 41
I use fpc 2.6.2 and Lazarus 1.0.12 on a mac Mavericks I create a variable like this
var
MyVar : 7..200;
If I assign a value to MyVar
outside the subrange of 7..200
, the compiler still accepts the value up to 255. If I assign 256 then the value in MyVar
becomes 0
and if I assign 257
then MyVar
becomes 1 and so on. Has anybody got an idea what is going on?
Upvotes: 4
Views: 1864
Reputation: 1593
I believe FreePascal actually creates a byte type variable (because it's the smallest type that contains given range), which accepts values 0..255. Number 256 requires two bytes 1 and 0 (0000 0001 0000 0000) in binary. The lowest get's assigned to MyVar. If you turn on overflow checking your program will raise an exception instead of silently cutting the value. You can do this via -Co
compiler argument or using {$Q-}
and {$Q+}
compiler directives in source code.
As for assigning values below 7 or above 200 you can avoid this by switching on range checking using command line option -Cr
. In source code you can also use {$R-}
and {$R+}
directives to turn range checking off and on respectively.
I would recommend always turning on overflow and range checking during development. It does have some performance penalty so you can turn it off in release if it starts hurting performance.
Upvotes: 1
Reputation: 125679
You haven't created a sub-range. :-) You've declared a variable (using var
). To properly create a sub-range, you first declare a type
:
type
TMyRange = 7..200;
You then declare your variable as that type
:
var
MyVar: TMyRange;
Attempts to assign a value outside that range cause a compiler error (for instance, in Delphi with range checking on):
MyVar := 201;
[dcc32 Error] Project1.dpr(22): E1012 Constant expression violates subrange bounds
It's usually a really good idea to turn on range checking so that the compiler will work for you. (It's usually a good idea to turn on overflow checking too, at least during development. See the rest of this answer for why.)
As far as the behavior you're seeing, the compiler will create the smallest size ordinal type that will hold the sub-range (in this case, a Byte
). In this case, you haven't declared a subrange, but a simple variable, which the compiler fits into a byte
.
As a byte can hold values from 0..255
, and you have declared a byte variable, the max value it can hold is 255. If you assign 256 (and don't have overflow checking turned on in your compiler options), the value overflows and wraps around to the minimum value (zero) + 1 (the number of bits it overflowed). Assigning 257
wraps around to the minimum value + 2 (again, the amount it overflowed).
Upvotes: 3