Minus

From Free Pascal wiki
Jump to navigationJump to search

English (en) suomi (fi) français (fr) русский (ru)

-

In ASCII, the character code decimal 45 (or hexadecimal 2D) is defined to be - (hyphen-minus).

Occurrences

The symbol - (pronounced “minus”) is used to

  • indicate the negative sign of a number literal
  • subtract two numbers (using infix notation)
  • form the difference of two sets.
program minusDemo(input, output, stderr);

var
	x: longint;
	g: longint;
	m: set of (foo, bar);

begin
	// unary operator: negative sign
	x := -42;                     // x becomes negative 42
	
	// binary operator: difference of numbers
	g := 144 - 169;               // g becomes negative 25
	
	// binary operator: difference of sets
	m := [foo, bar] - [bar];      // m becomes {foo}
end.

Minus is also a unary operator. You can write such stupid expressions as ----+--+--+--8.

Operation with numbers

Beware: The result's target of subtractions (and sign inversions) should be a signed integer. If it's not, with {$rangechecks} directive enabled, it will possibly cause a run-time error. In any other case an arithmetically wrong result is produced.

program faultySubtraction(input, output, stderr);

var
	x, y: longword;

begin
	y := 1;
	{$push}
	{$rangechecks off} // otherwise the next expression
	x := 0 - y;        // yields RTE 201
	{$pop}
	
	writeLn(x);
end.

This program prints 4294967295, which equals to high(longword) because of the (unsigned) integer overflow.

However note, there are situations where negative signs do not necessarily provoke an error. Attempting to store a “negative” zero won't harm:

 1program minusOperations(input, output, stderr);
 2
 3{$rangeChecks on}
 4
 5var
 6	n: longword;
 7
 8begin
 9	// "negative" zero equals to (sign-less) zero
10	n := 0;
11	n := -n;

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.

13	// intermediate results can be out of range:
14	n := 1;
15	n := n - n - n + 1;
16end.

This whole program will finish with an exitCode of zero (that means “successful” [actual value might vary among platforms]).

In consequence of the latter mentioned behavior: Integer overflows in the processor's native type can not be caught (in that way). In assembler you would have access evaluating several status flags, but in Pascal you do not. Instead you can use {$overflowChecks} which will evoke a run-time error.

 1program overflowChecksDemo(input, output, stderr);
 2
 3{$overflowChecks on}
 4
 5var
 6	n: nativeInt;
 7
 8begin
 9	n := high(n);
10	n := n + 1;   // will yield RTE 215
11end.

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:

 1program overflowAnticipation(input, output, stderr);
 2
 3var
 4	n: {$ifdef CPU64} int64 {$else} longint {$endif};
 5
 6begin
 7	// untreated
 8	n := high(n);
 9	n := n + 1;
10	writeLn(n); // prints low(n)
11	
12	// anticipated: reverse operation and comparison w/ 1st operand
13	n := high(n);
14	if high(n) - 1 < n then
15	begin
16		halt(1);
17	end;
18	n := n + 1;
19	writeLn(n);
20end.

Obviously this won't be as efficient as testing the overflow status flag, and here, without any re-used constant, is even prone to programming errors (consider the situation changing the subtrahend in one line of code only).


navigation bar: topic: Pascal symbols
single characters

+ (plus)  •  - (minus)  •  * (asterisk)  •  / (slash)
= (equal)  •  > (greater than)  •  < (less than)
. (period)  •  : (colon)  •  ; (semi colon)
^ (hat)  •  @ (at)
$ (dollar sign)  •  & (ampersand)  •  # (hash)
' (single quote)

character pairs

<> (not equal)  •  <= (less than or equal)  •  := (becomes)  •  >= (greater than or equal)

 •  >< (symmetric difference)  •  // (double slash)