user3182467
user3182467

Reputation: 41

Free pascal subrange

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

Answers (2)

Avo Muromägi
Avo Muromägi

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

Ken White
Ken White

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

Related Questions