Evaluation of expressions in operators (detailed explanation of implicit type conversion) and operator properties

Expression evaluation


The order in which expressions are evaluated is partly determined by the priority and associativity of operators. The operands of some expressions may need to be converted to other types during evaluation.

Implicit type conversion

1. Shaping and lifting

Secretly converted, and can not be seen intuitively

The integer arithmetic operation of C is always performed at least with the precision of the default integer type.
To achieve this precision, the characters and short operands in the expression are converted to normal integers before use. This conversion is called integer promotion.

Significance of integer improvement:

The integer operation of the expression shall be executed in the corresponding operation device of the CPU, and the byte length of the operand of the integer operator (ALU) in the CPU
Generally, it is the byte length of int and the length of the general register of CPU.
Therefore, even if the two char types are added, they will actually be converted to the standard length of integer operands in the CPU when executed by the CPU
Degrees.
General purpose CPU (general purpose CPU) is difficult to directly realize the direct addition of two 8-bit bytes (although machine instructions
There may be such byte addition instructions in). Therefore, all integer values whose length may be less than int length in the expression must be converted first
Change to int or unsigned int, and then send it to the CPU to execute the operation.

int main()
{
	char a = 3;
	//00000011
	//000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
	char b = 127;
	//01111111
	//00000000000001111111 B after lifting
	char c = a + b;//a and b will be shaped and lifted
	//00000000000000000010000001 -- after adding
    //Only 8 bits can be stored in c:
	//10000010-c now wants% d shaping and printing, and C wants to improve
    //c after lifting:
    //11111111111111111111111110000010 complement
	//11111111111111111111111110000001
    //10000000000000000000000001111110
    //-126
	printf("%d\n", c);
	return 0;
}

Both a and b are not large enough for int, so they need to be shaped and promoted. The values of a and b are promoted to ordinary integers, and then the addition operation is performed.
After the addition operation is completed, the result will be truncated and then stored in c.

How to improve?

Integer promotion is promoted according to the sign bit of the data type of the variable.

//Shaping and lifting of negative numbers
char c1 = -1;
variable c1 Binary bit of(Complement)There are only 8 bits in:
11111111
 because char Is signed char
 Therefore, when shaping and lifting, the high supplementary symbol bit is 1
 The result of the promotion is:
11111111111111111111111111111111
//Positive integer lifting
char c2 = 1;
variable c2 Binary bit of(Complement)There are only 8 bits in:
00000001
 because char Is signed char
 Therefore, when shaping and lifting, the high supplementary symbol bit is 0
 The result of the promotion is:
00000000000000000000000000000001
//Unsigned shaping lifting, high complement 0

Examples of shaping and lifting:

int main()
{
    char a = 0xb6;//Binary sequence: 10110110
    short b = 0xb600;//1011011000000000
    int c = 0xb6000000;//10110110000000000000000000000000
    if(a==0xb6)//Comparing the size is also an operation, and the shaping promotion occurs here
    printf("a");
    if(b==0xb600)//Comparing the size is also an operation, and the shaping promotion occurs here
    printf("b");
    if(c==0xb6000000)//c is shaping, which can be printed without lifting
    printf("c");
	return 0;
}

The size comparison operation is required in the if judgment statement. A is of char type and b is of short type. Therefore, a and b need to be reshaped and upgraded. After reshaping and upgrading, there is a change. c does not need reshaping and upgrading, so it can be printed

int main()
{
    char c = 1;
    printf("%u\n", sizeof(c));
    printf("%u\n", sizeof(+c));
    printf("%u\n", sizeof(-c));
    return 0;
}

The expression in sizeof brackets does not participate in the operation! If the type of the expression we want to generate is int, then we can figure out what the type of the expression we want to generate is int.

2. Arithmetic conversion

For example, if an int and a long are operated on, the int is converted to long for operation, and the small one is converted to the large one for operation

Properties of operators

Three influencing factors of expression

  1. operator precedence

    The priority depends on the priority when two adjacent operators are different

  2. Associativity of operators

    When two adjacent operators are the same, look at associativity

  3. Whether to control the evaluation order.

If the expression we write cannot determine the unique calculation path through the properties of the operator, there is a problem with this expression
of

Some expression problems

Code 1

//The evaluation part of the expression is determined by the priority of the operator.
//Expression 1
a*b + c*d + e*f

Code 1 can only ensure that * is calculated earlier than + due to its higher priority than + during calculation, but the priority does not determine that the third * is executed earlier than the first +

a*b
c*d
a*b + c*d
e*f
a*b + c*d + e*f
 Or:
a*b
c*d
e*f
a*b + c*d
a*b + c*d + e*f

If a, b, c, d, e and f are expressions, the uncertainty of operation order is a big problem.

Code 2

//Expression 2
c + --c;

The priority of the same operator can only determine whether the operation of self subtraction - precedes the operation of + but we can't know whether the left operand of + operator is evaluated before or after the right operand, so the result is unpredictable and ambiguous.

Code 3

int main()
{
    int i = 10;
    i = i-- - --i * ( i = -3 ) * i++ + ++i;
    printf("i = %d\n", i);
    return 0;
}

This code runs differently in different compilers.

Code 4

int fun()
{
  static int count = 1;
  return ++count;
}
int main()
{
  int ret;
  ret = fun() - fun() * fun();
  printf( "%d\n", ret);//How much output?
  return 0;
}

The calling order of functions cannot be determined by the priority of operators

Code 5

#include <stdio.h>
int main()
{
    int i = 1;
    int ret = (++i) + (++i) + (++i);
    printf("%d\n", ret);
    printf("%d\n", i);
    return 0;
}
//Try to execute gcc compiler in linux environment and VS2019 environment. See the results.

The compilation result in Linux environment is 10

The compilation result in vs2019 environment is 12

Keywords: C

Added by gamerzfuse on Fri, 11 Feb 2022 21:24:43 +0200