Sign in Join
Wiki copytemporary

Minus: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Minus

OldNewLine
1+<div style="float:right; margin: 0 10px 10px 0; padding:40px; font-size:500%; font-family: Georgia; background-color: #f9f9f9; border: 2px solid #777777;">
2+
3+\-
4+
5+</div>
6+
7+In [[ASCII]], the character code decimal `45` (or [[Hexadecimal|hexadecimal]] `2D`) is defined to be `-` (hyphen-minus).
8+
9+## Occurrences
10+
11+The symbol `-` (pronounced “minus”) is used to
12+
13+- indicate the negative sign of a number literal
14+- subtract two numbers (using infix notation)
15+- form the difference of two [[Set|sets]].
16+
17+``` pascal
18+program minusDemo(input, output, stderr);
19+
20+var
21+ x: longint;
22+ g: longint;
23+ m: set of (foo, bar);
24+
25+begin
26+ // unary operator: negative sign
27+ x := -42; // x becomes negative 42
28+
29+ // binary operator: difference of numbers
30+ g := 144 - 169; // g becomes negative 25
31+
32+ // binary operator: difference of sets
33+ m := [foo, bar] - [bar]; // m becomes {foo}
34+end.
35+```
36+
37+Minus is also a unary operator. You can write such stupid expressions as `----+--+--+--8`.
38+
39+## Operation with numbers
40+
41+Beware: The result's target of subtractions (and sign inversions) should be a *signed* integer. If it's not, with [[sRangechecks|{$rangechecks}]] [[Compiler directive|directive]] enabled, it will possibly cause a [[runtime error|run-time error]]. In any other case an arithmetically wrong result is produced.
42+
43+``` pascal
44+program faultySubtraction(input, output, stderr);
45+
46+var
47+ x, y: longword;
48+
49+begin
50+ y := 1;
51+ {$push}
52+ {$rangechecks off} // otherwise the next expression
53+ x := 0 - y; // yields RTE 201
54+ {$pop}
55+
56+ writeLn(x);
57+end.
58+```
59+
60+This program prints `4294967295`, which equals to `high(longword)` because of the (unsigned) integer overflow.
61+
62+However note, there are situations where negative signs do not necessarily provoke an error. Attempting to store a “negative” zero won't harm:
63+
64+``` pascal
65+program minusOperations(input, output, stderr);
66+
67+{$rangeChecks on}
68+
69+var
70+ n: longword;
71+
72+begin
73+ // "negative" zero equals to (sign-less) zero
74+ n := 0;
75+ n := -n;
76+```
77+
78+Also note, arithmetic integer operations are done with the processor's native integer type. Although intermediate results fall out of range, the code generated by `{$rangechecks on}` ensures the type's boundaries aren't exceeded *after* the result's already stored.
79+
80+``` pascal
81+ // intermediate results can be out of range:
82+ n := 1;
83+ n := n - n - n + 1;
84+end.
85+```
86+
87+This whole program will finish with an [`exitCode`](https://www.freepascal.org/docs-html/rtl/system/exitcode.html) of zero (that means “successful” \[actual value might vary among platforms\]).
88+
89+In consequence of the latter mentioned behavior: Integer overflows in the processor's native type can not be caught (in that way). In [[Assembly language|assembler]] you would have access evaluating several status flags, but in [[Pascal]] you do not. Instead you can use [[sOverflowchecks|{$overflowChecks}]] which will evoke a run-time error.
90+
91+``` pascal
92+program overflowChecksDemo(input, output, stderr);
93+
94+{$overflowChecks on}
95+
96+var
97+ n: nativeInt;
98+
99+begin
100+ n := high(n);
101+ n := n + 1; // will yield RTE 215
102+end.
103+```
104+
105+The generated code by the `{$overflowChecks}` directive is the *most efficient*, since it directly uses available status flag evaluation instructions (e.g. “jump if overflow occured”). On the downside, a once triggered RTE will inevitably terminate the program. If this is regarded as counter-productive, you would have to recognize situations leading to overflows on your own:
106+
107+``` pascal
108+program overflowAnticipation(input, output, stderr);
109+
110+var
111+ n: {$ifdef CPU64} int64 {$else} longint {$endif};
112+
113+begin
114+ // untreated
115+ n := high(n);
116+ n := n + 1;
117+ writeLn(n); // prints low(n)
118+
119+ // anticipated: reverse operation and comparison w/ 1st operand
120+ n := high(n);
121+ if high(n) - 1 < n then
122+ begin
123+ halt(1);
124+ end;
125+ n := n + 1;
126+ writeLn(n);
127+end.
128+```
129+
130+Obviously this won't be as efficient as testing the overflow status flag, and here, without any *re-used* [[Constant|constant]], is even prone to programming errors (consider the situation changing the subtrahend in one line of code only).
131+
132+---
133+*From the Free Pascal wiki, page "Minus", as it stood on 2022-08-06 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history