There are three types of expressions: Primary Expressions, Unary Operator Expressions and Binary Operator Expressions. These will be described in turn.
Functions are described in the next section.
Primary expressions may be further divided into five kinds:
1) Variables,
2) Array Elements,
3) Literals,
4) Function Calls, and
5) Parenthesized Expressions.
An array element may be used as an expression if 1) the subscript referencing it is in the range defined when the array was declared, and 2) the type of the element is scalar. Since the subscript itself may be a variable and the contents of an array ele-ment may be of any type, the test for the above conditions is made at reference time.
Only functions which return a scalar may be used as an expression. The syntax of a function call is:
<function name> ( <argument list> )
The contents of the argument list vary depending upon the function being in-voked. The reader is referred to the detailed descriptions of the individual func-tions for the specification of the arguments required by each. Note that the argu-ment list may be empty for some functions, but the delimiting parentheses are still required. As with “C”, function arguments are passed by value, and the ar-guments themselves will not be affected in any way by the function call.
A parenthesized expression consists of a left parenthesis, any expression, and then a right parenthesis — ( <expression> )
The purpose of the parenthesized expression is simply to delimit the enclosed ex-pression for grouping purposes. Normally the enclosed expression will be a binary operator expression, although any type of expression is valid. The classic example is a grouping to defeat the normal precedence of operators with a binary operator ex-pression — ( x + 1 ) / 2
Only variables of type scalar may be used as an expression. Since variables of that type always have a value defined, the use of a variable as an expression is just a ref-erence to that value.
Two unary operators are provided, logical negation ( ! ), and arithmetic negation ( – ). In both cases the syntax is:
<operator><primary expression>
where <operator> is either “!” or “-”. Any primary expression is valid, but only a primary expression. Logical negation results in a value for the expression of ei-ther 0 (FALSE) or 1 (TRUE). A value of 1 results when the <primary expression> has a value of zero. A value of 0 results when the <primary expression> has any other (non-zero) value. Arithmetic negation simply changes the sign of the value of the <primary expression>. Zero is unsigned and unaffected by this operator. Logical negation takes precedence over arithmetic negation.
A binary operator expression consists of 2 expressions (of any kind) separated by a binary operator. There are 12 binary operators, which have 5 different levels of precedence, namely:
* / highest precedence
+ -
== != >= <= > <
&&
|| lowest precedence
All binary operators have a lower precedence than the unary operators. All bi-nary operators are left associative. The individual operators will be discussed in order of decreasing precedence.
Multiplication ( * ) and division ( / ) have the same precedence. All arithmetic is per-formed in single precision floating point form. Division by zero is invalid and results in a terminated execution. Addition ( + ) and subtraction ( – ) have the same prece-dence, which is lower than multiplication or division. The computa-tion is performed in single precision floating point form.
The operators “<”, “>”, “<=”, “>=”, “==” and “!=” are collectively known as trela-tion operators. They represent “less than”, “greater than”, “less than or equal to”, “greater than or equal to”, “equality”, and “not equal”, respectively. All the relation operators have the same precedence. The relation operators compare the values of 2 expressions. The result of such a comparison is either 1 in the case where the speci-fied relationship exists (the TRUE case) or 0 in the case where the relation does not exist (FALSE).
All comparisons are between single precision floating point numbers. The user is therefore advised to exercise care when using tests for equality. A second poten-tial problem could occur because of the left associativity combined with all rela-tion op-erators having the same precedence and the left to right evaluation order of expres-sions. The user is urged to use explicit grouping whenever more than one relation operator is needed.
Consider, for example,
a > b > 3
This will always evaluate to 0 (FALSE), because the associativity results in
( a > b ) > 3
and the result of a > b must be either 1 or 0, neither of which is greater than 3.
The logical AND operator ( && ) interprets the two expressions as truth values and performs the logical intersection. An expression is considered true if its value is non-zero, and false if its value is zero. The result of the intersection is either 1 (in the case where the expressions are both true) or 0 (for all other cases). Note that the left ex-pression is evaluated first, and if it is false then the result is deter-mined and the right expression is not inspected at all. This behavior is similar to the “C” language and is sometimes useful when the value of an expression might not be well defined (as with arrays for instance).
The logical OR operator ( || ) interprets the two expressions as truth values and performs the logical union. An expression is considered true if its value is non-zero, and false if its value is zero. The result of the union is either 1 (in the case where ei-ther of the expressions are true) or 0 (in the case where both expressions are false). Note that the left expression is evaluated first, and if it is true then the result is de-termined and the right expression is not inspected at all. This behavior is similar to the “C” language and is sometimes useful when the value of an ex-pression might not be well defined (as with arrays for instance).