Bracketing Operator ()

This page was translated by a robot.

In programs, several operators often appear one after the other. The order in which these operators are processed is clearly defined based on the processing direction and ranking . In some cases, however, a different order is desirable. The purpose of bracketing operators is to specify this order explicitly. Operators are ()bracketed with round brackets.

Details

The operator bracket expects an operand as rvalue or lvalue within the bracket and has no processing direction . The return value corresponds to the operand in brackets and can therefore be either an rvalue or an lvalue .

The operator bracketing is not an operator in the true sense, since it only gives a hint for the compiler and therefore does not produce any code. This is also the reason why this operator has no processing direction: There is nothing to process.

The parentheses must be well-formed, i.e. each closing parenthesis )must have been introduced by a clear opening parenthesis at some point before (.

The operator bracketing is always treated with priority according to the operator ranking . Listed below are some cases where operator bracketing is common.

Brackets when in Doubt

When it is unclear what direction of processing or hierarchy operators have among themselves, when inexplicable phenomena occur in a line of code, when it is necessary to ensure that the math is correct, when it is unclear where which type is, when it is uncertain whether a code fragment will come later could be expanded...

It is ALWAYS recommended to use parentheses. Brackets NEVER hurt!

Bracketing of Arithmetic Calculations

The bracketing of mathematical expressions is necessary and helpful, since operators often appear one after the other that have the same processing direction and the same ranking.

The effect of parentheses can be demonstrated using the subtraction operator :




0
10
6
4
#include <stdio.h>

int main(){
  printf("%d\n", 10 -   5 -   3 - 2     );
  printf("%d\n", 10 - ( 5 -   3 - 2   ) );
  printf("%d\n", 10 - ( 5 - ( 3 - 2 ) ) );
  printf("%d\n", 10 -   5 - ( 3 - 2 )   );
}

Basically, the processing direction and ranking generally follow an intuitive understanding of the respective operators. The usual mathematical operators, for example, follow the usual rules of mathematics, such as the associative law (dot-before-dash rule):

10
14
printf("%d\n",  4 + 3  * 2);
printf("%d\n", (4 + 3) * 2);

However, it must not be forgotten that the compiler basically does not understand anything about mathematics and therefore does not automatically implement common simplifications correctly. For example, in mathematics, it is common for the expression 2π(two pi) to be perceived as a unit. This is not the case in C and C++. The following example calculates the conversion from radians to degrees. Although the conversion factor was enclosed in brackets in the first line for visual support, the calculation is only correct in the second line due to the additional brackets.

1776.525791
180.000000
printf("%f\n", 3.14159 * (360. /  2. * 3.14159 ));
printf("%f\n", 3.14159 * (360. / (2. * 3.14159)));

Brackes for Code Readability

The sequence of the operator evaluation is often clear, but brackets are used to give the programmer a better overview from a purely visual point of view.

void cross_product(T* d, const T* a, const T* b){
  d[0] = (a[1] * b[2]) - (a[2] * b[1]);
  d[1] = (a[2] * b[0]) - (a[0] * b[2]);
  d[2] = (a[0] * b[1]) - (a[1] * b[0]);
}

Parentheses make it easier for the programmer to read and find errors, especially when calculating indices.





Arraysize: 8
Maxindex:  7

(1,2) = 5
(0,3) = 6
int i;
int numy = 4;
int numx = 2;
int a[numy * numx];
printf("Arraysize: %d\n", (numy * numx));
printf("Maxindex:  %d\n", (numy * numx) - 1);
for(i=0; i < (numy * numx); i++){a[i] = i;}
printf("(1,2) = %d\n", a[(2 * numx) + 1]);
printf("(0,3) = %d\n", a[(3 * numx) + 0]);

Brackets for Arrays, Pointers and Dereferences

When pointers or arrays are converted to a specific type using a cast, it is not always clear which part of the expression is actually being cast. The following example attempts to address a two-dimensional array as a one-dimensional array:


Number: -1073743992
Number: 2
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
printf("Number: %i\n",  (int*)a [1]);
printf("Number: %i\n", ((int*)a)[1]);

The first line incorrectly assumes that the cast is applied to the two-dimensional array a. In fact, however, in this line, the indexed element 1of the two-dimensional array is addressed first, which intreturns a pointer to a . This is then (unnecessarily) cast and the result (the pointer) is output as a decimal number. In the second line, the operator brackets ensure that the cast is intended for the two-dimensional array a, after which the correct element is read out with the element operator.

In the following example, a two-dimensional array is addressed using the dereference operator. Depending on the bracketing, this can lead to different (and potentially undesirable) results:


Number: 2
Number: 4
int numbers[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
printf("Number: %d\n", (*numbers)[1]);
printf("Number: %d\n",  *numbers [1]);

While in the first row the first three-tuple {1,2,3}is dereferenced first and then the element 2with an index [1]is selected, in the second row the three-tuple {4,5,6}with an index [1]is first selected and then the first element is 4dereferenced.

Parentheses for Arithmetic Conversions

Due to the automatic arithmetic conversion built into C and C++ , it is possible for operators to be processed in a suboptimal order. The following example performs a calculation whose result and all intermediate results could be floatsafely expressed using a number, but the calculation itself performs implicit conversions, which lose precision. The exact result can only be determined by using the brackets, since the two intvalues ​​are not converted here.

0.123001
0.123000
printf("%f\n",  0.123f +  100 - 100 );
printf("%f\n",  0.123f + (100 - 100));

Such and similar effects can be found in particular with extreme values, where precision is lost due to an automatic arithmetic conversion. These peculiarities will not be discussed further here, but it is recommended not to use the automatic arithmetic conversion carelessly and, if in doubt, to use parentheses or even casts.

When using casts, sometimes additional parentheses need to be used. In the following example, the correct result can only be output as a decimal number by bracketing the entire calculation.

1.5 + 1.5 = 3.000000
1.5 + 1.5 = 3
printf("1.5 + 1.5 = %f\n",       1.5 + 1.5 );
printf("1.5 + 1.5 = %d\n", (int)(1.5 + 1.5));

Bracketing of the Condition Operator

The conditional operator is a popular shortcut to avoid cumbersome ifstructures . However, due to its order of precedence, this operator is treated with less priority than most other operators. The following example illustrates the need to bracket the conditional operator correctly:




0
50
51
int i = 1 +     1 < 2   ? 50 : 0  ;
int j = 1 +   ( 1 < 2 ) ? 50 : 0  ;
int k = 1 + ( ( 1 < 2 ) ? 50 : 0 );
printf("%d\n", i);
printf("%d\n", j);
printf("%d\n", k);

When assigning to the variable i, the addition operator has priority over the less than operator , which is used to add 1 + 1up. Since the less than operator is then treated with priority over the conditional operator, what is 2 < 2evaluated falseis what serves as the first argument for the conditional operator, which thus 0returns.

When assigning to the variable j, the less than operator is treated with priority over the addition operator due to the brackets , but the addition operator is also treated with priority over the condition operator, which means that what is used as the first argument for the condition operator is evaluated, which thus returns .1 + true250.

Only when the variable kis assigned is it checked whether 1is less than 2, to which 50is 1added.

It should be noted that this last bracketing is not necessary for simple assignments without further operators, since assignments are treated with even less priority than the conditional operator..



50
50
int m =   1 ? 50 : 0  ;
int n = ( 1 ? 50 : 0 );
printf("%d\n", m);
printf("%d\n", n);

Other Cases for Bracketing

The round brackets are also used for brackets in macros. Some important cases can be found in the #definedirective.

There are many special situations in which parentheses are useful or even necessary. Only a few important peculiarities of the languages ​​C and C++ were mentioned here with reference to a possible source of error. The principle mentioned above still applies: In case of doubt: use brackets!