Your proposition seems to solve the problem, but I don't understand it. :)
Your proposition seems to solve the problem, but I don't understand it. :)Neither do I, since according to https://www.freepascal.org/docs-html/current/ref/refsu4.html#x26-250003.1.1 the largest ShortInt is 127.
To be fair, though, casting to Byte should work equally well (or better).
Warning: range check error while evaluating constants (-193 must be between 0 and 255)
Solution is in reply #1 above.
Warning: range check error while evaluating constants (-193 must be between 0 and 255)
Another reason to turn warnings off:
Your proposition seems to solve the problem, but I don't understand it. :)
Neither do I, since according to https://www.freepascal.org/docs-html/current/ref/refsu4.html#x26-250003.1.1 the largest ShortInt is 127.
MarkMLl
Why FPC 3.2.0 gives warning at explicit casting -193 to byte, is another question... ;)
When a previously declared ordinary constant is used in the code, the compiler will insert the actual value of the constant instead of the constant name.Even this code
As I understand it, you cannot use typed constants in expression in a constant declaration, because they in fact are some kind of variables (are placed in memory and initialized) ....
As I understand it, you cannot use typed constants in expression in a constant declaration, because they in fact are some kind of variables (are placed in memory and initialized), while ordinary constants are analog of #define in C. This is quote from https://www.freepascal.org/docs-html/current/ref/refse9.html#x21-200002.1 :
This directive does not make them ordinary constants, it only tells compiler to place them in read-only memory (if architecture and system allow this).As I understand it, you cannot use typed constants in expression in a constant declaration, because they in fact are some kind of variables (are placed in memory and initialized), while ordinary constants are analog of #define in C. This is quote from https://www.freepascal.org/docs-html/current/ref/refse9.html#x21-200002.1 :
Although I'd tried using the directive which should have disabled that.
MarkMLl
PS: interestingly, the following code gives a compiler error:Error: range check error while evaluating constants (4294967103 must be between 0 and 255)
const a = 128; b = 64; c : byte = lo(not (a or b));
The first solution assumes both a and b are bytes.
In retrospect, I rather wish I'd not got involved in this :-)Me too. This discussion practically scared the hell out of me
reg |= BITNO;
reg &= ~BITNO;
to set/clear a bit in a IO register which the C compiler usually translates the latter to a single assembly instruction. The first solution assumes both a and b are bytes.
If a and b are ordinary constants, they cannot be bytes. They do not reside in memory. They are evaluated to NUMBERS with some rules by compiler (for C we would say by preprocessor) before real compilation.
For ordinary constants we can speak only about range.
SizeOf(NOT SomeValue) equals SizeOf(PtrInt)
that is 4 or 8 bytes
SizeOf(NOT SomeValue) equals SizeOf(PtrInt)
that is 4 or 8 bytes
Not correct! Tested with FPC 3.2
var B: Byte; I: Integer; begin I := SizeOf(not B); // = 1!
And whyshould be treated differently than
$FF xor B?
not B
*snip*
How about you do the correct test!
const b=1; begin WriteLn(SizeOf(b)); WriteLn(SizeOf(NOT b)); //OR WriteLn(SizeOf(1)); WriteLn(SizeOf(NOT 1));
Constants, remember? Ordinal constants.
And whyshould be treated differently than
$FF xor B?
not B
Hopefully you see the reason now.
not (128 or 64)
and $FF xor (128 or 64)
are non-terminal <expr> on terminals $FF, 128, 64 (all fit in a byte, i.e. 0..2^8-1) and I can't see the reason the former will be widened to PtrInt and the latter -not.*snip*
How about you do the correct test!
const b=1; begin WriteLn(SizeOf(b)); WriteLn(SizeOf(NOT b)); //OR WriteLn(SizeOf(1)); WriteLn(SizeOf(NOT 1));
Constants, remember? Ordinal constants.
I see.
But you wrote:
SizeOf(NOT SomeValue) equals SizeOf(PtrInt)
It's a sloppy writing.
And whyshould be treated differently than
$FF xor B?
not B
Hopefully you see the reason now.
Actually, no. May be you're hopeful that I can differentiate between (128 or 64) and $FF but I can't. Both:Code: [Select]not (128 or 64)
andCode: [Select]$FF xor (128 or 64)
are non-terminal <expr> on terminals $FF, 128, 64 (all fit in a byte, i.e. 0..2^8-1) and I can't see the reason the former will be widened to PtrInt and the latter -not.
Nowhere I can see a type hint to the compiler as it would be if they're declared as variables (e.g. V: Type).
Why the widening rules for not and xor would differ?
Hi!
Perhaps one usefull tip:
If you use NOT without any type casting, the result is in the native size of your machine:
On 32Bit machines it is 4 bytes
On 64Bit machines it is 8 bytes
It does not matter if the input is a byte, a word or an integer.
Winni
Hi !+1 for mentioning UCSD Pascal.
I have read the sizeof documentation of UCSD Pascal 40 yers ago.Since then has not much changed.
Winni
If Delphi widens the result of NOT, FPC is going to follow for compatibility. Otherwise it is a bug.is not an excuse.
(@engkin) it can be considered as a bug.
*snip*I'd rather not use sizeof that way.
Since you are that sure, maybe you can file a bug report.
*snip*I'd rather not use sizeof that way.
Since you are that sure, maybe you can file a bug report.
What bothers me more is the different interpretations of the otherwise identical bitwise not and xor
What bothers me more is the different interpretations of the otherwise identical bitwise not and xor
I've taught a time ago, that constants are lexical substitutions, not integers. I doubt the things have changed since.
BTW, does anyone know where a decent documentation for FPC SizeOf() can be found?
I think for the original OP question it is:
const a = 128; b = 64; c = not byte(a or b);
This code sets c to -193, this is not a byte (to be correct, not in range 0...255), what OP wants.
Moreover, casting (a or b) to byte is useless here: 128 or 64 = 192, byte(192) = 192.
You've taught a time ago, that constants are lexical substitutions...
This code sets c to -193, this is not a byte (to be correct, not in range 0...255), what OP wants.
Moreover, casting (a or b) to byte is useless here: 128 or 64 = 192, byte(192) = 192.
You've taught a time ago, that constants are lexical substitutions...
Quite not useless, since doesn't give a range check warning as with: c = byte(not (a or b));
I was taught well enough ;)
Once more:
c = not byte(a or b) = not byte(128 or 64) = not byte(192) = not 192 = -193
is absolutely the same as
c = not (a or b) = not (128 or 64) = not 192 = -193
which also gives no warning.
@BobDog
I think for the original OP question it is:
const a = 128; b = 64; c = not byte(a or b);
I must correct myself in my earlier post - in the latter versions of C/C++ sizeof is defined also on expressions as 'size of the static type of the expression'. Assuming our SizeOf() is working in a similar way, perhaps the lack of a type hint makes him to return SizeOf(not 1) = SizeOf(PtrInt).
BTW, does anyone know where a decent documentation for FPC SizeOf() can be found?
@tetrastes
Thank you for your example! It shows me mostly the negative numbers two's complement representation.
I've taught a time ago, that constants are lexical substitutions, not integers. I doubt the things have changed since.
Once more:
c = not byte(a or b) = not byte(128 or 64) = not byte(192) = not 192 = -193
is absolutely the same as
c = not (a or b) = not (128 or 64) = not 192 = -193
which also gives no warning.
c = byte(not(a or b)) Gives the warning. (FPC 3.2)
c = not byte(a or b) Does not.
Instead of repeating, you should try to solve it with types, not numbers.
BUT this is NOT what OP wants, because
c = byte(not (a or b)) = ... = 63
ivanov, yes no warning, great. But now it's 4 bytes.Oops, sorry!
@tetrastesYes, typecast, and
The NOT just don't have a clue for the type of its operand and sign-extends making the value negative. Just give him what he needs, typecast, that's it.
Just one more typecast: c = byte( not byte(a or b) );gives the same warning and the same binary as
@tetrastesYes, typecast, and
The NOT just don't have a clue for the type of its operand and sign-extends making the value negative. Just give him what he needs, typecast, that's it.QuoteJust one more typecast: c = byte( not byte(a or b) );gives the same warning and the same binary as
c = byte( not (a or b) );
I fail to see how these two statements could contradict. If you still think the same after reading this post then please feel free to elaborate to make me better understand.Code: [Select]Remark: The compiler decides on the type of an integer constant
based on the value: An integer constant gets the smallest possible
signed type.
...
constants in range 128..255 are mapped to byte, etc.
...
These two statements contradict each other, am I wrong?
That means constants in the range -128..127 are mapped to shortint,
constants in range 128..255 are mapped to byte, etc.
64
1
01000000
128
1
10000000
192
1
11000000
-193
8
1111111111111111111111111111111111111111111111111111111100111111
*snip*My point was that, the Sizeof() for example when used on expression, must evaluate the type of the expression, not the expression itself. Then substituting with the terminals (e.g. 128 for a, 64 for b) into the expression (byte(not (a or b)), and given the rules for expansion, we should be able to determine at which step the sign-extension takes place and to put a proper typecast to prevent it. But it turns out it was just a speculation.
What types are you talking about for ordinary constants? Show how " to solve it with types", I don't afraid to say that I do not know that.
An integer constant gets the smallest possible SIGNED type.I fail to see how these two statements could contradict. If you still think the same after reading this post then please feel free to elaborate to make me better understand.Code: [Select]Remark: The compiler decides on the type of an integer constant
based on the value: An integer constant gets the smallest possible
signed type.
...
constants in range 128..255 are mapped to byte, etc.
...
These two statements contradict each other, am I wrong?
The first match in table (3.3) is used.By using the table you are able to determine the order of precedence.
y.ivanov wrote:Thank you for the +1 but I can't really take the credit for that as others have (more or less) stated the same.
@molly
+1 for your detailed explanation
Thank you for explanations, I understand all. But I still think that the first statement must be "An integer constant gets the smallest possible INTEGER type".