Detailed explanation of operators (very detailed)

Subscript access [ ], function call ()

[ ] subscript reference operator

Operands: an array name + an index value

int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[ ]的两个操作数是arr和9
3+5     35是加号的两个操作数

function call operator

Accepts one or more operands: the first operand is the function name, and the remaining operands are the parameters passed to the function

#include <stdio.h>
void test1()
{
    
    
printf("hehe\n");
}
void test2(const char *str)
{
    
    
printf("%s\n", str);
}
int main()
{
    
    
test1(); //这⾥的()就是作为函数调⽤操作符。
test2("hello bit.");//这⾥的()就是函数调⽤操作符。
return 0;
}

Note: The minimum operand of a function is only one, that is, there is only one function name, and no parameters (void) are passed
here. Sizeof is not a function, but an operator.

#include<stdio.h>
int main()
{
    
    
int a=10;
int n=sizeof(a)int n=sizeof a其实都一样
printf("%d\n",n);
return 0;
}

We can see that the difference between int n=sizeof(a) and int n=sizeof a is one (), and the function requires (), so sizeof is not a function but an operator

Operator properties: precedence, associativity

Operators in C language have two important attributes, priority and associativity. These two attributes determine the calculation order of expression evaluation (it can be approximated as a mathematical operation but there are still some differences)

priority

If an expression contains multiple operators during operation, which operator should be executed first?
In order to solve this problem, the priority of each operator is specified

 3 + 4 * 5;

In the above example, the expression 3 + 4 * 5 contains both the addition operator ( + ) and the multiplication operator ( * ). Since multiplication has a higher priority than addition, 4 * 5 will be calculated first instead of 3 + 4 first. (This is actually the mathematical operation rules)

Combination

When the priority of the two operators is the same, that is, when the operators are the same, we cannot judge which to calculate first according to the priority, so in this case we need to use associativity, but associativity depends on the situation , some will combine left (calculated from left to right), some will combine right (calculated from right to left), but most of them will be calculated from left to right.

5 * 6 / 2;

In the above example, * and / have the same priority. They are both left associative operators, so they are executed from left to right. 5 * 6 is calculated first, and then 6 / 2 is calculated. There are many priority orders of operators. The following is the priority order of some operators (arranged from high to low priority). It is recommended that you just remember the priorities of these operators. • Parentheses ( () ) • Auto-
increment
operation operator (++), decrement operator (-)
• Unary operators (+ and -)
• Multiplication (*), division (/)
• Addition (+), subtraction (-)
• Relational operators (<, > etc.)
• Assignment operator (=)

Since parentheses have the highest precedence, you can use it to change the precedence of other operators. Operator
insert image description here
precedence reference link

Expression evaluation

Integer promotion

Integer arithmetic in C is always performed with at least the precision of the default integer type ( that is, integers of data types smaller than 32 bits are promoted when the stored data type is smaller than the 32 bits stored by the integer type )
in order to obtain With this precision, character and short operands in expressions are converted to ordinary integers before use. This conversion is called integer promotion.

The meaning of integer promotion

The integer operation of the expression must be executed in the corresponding operation device of the CPU . The byte length of the operand of the integer arithmetic unit (ALU) in the CPU is generally the byte length of int , and it is also the length of the general-purpose register of the CPU .
Therefore, even if the addition of two char types is performed by the CPU, it must first be converted to the standard length of the integer operand in the CPU . ( So ​​anyway, it is the standard length of the integer operand to be converted, in order to use the increased byte length to make the accuracy more accurate )
It is difficult for a general-purpose CPU to directly add two 8-bit bytes directly (although the machine There may be such a byte addition instruction in the instruction
). Therefore, the various integer values ​​in the expression whose length may be smaller than the length of int must be converted to int or unsigned int before being sent to the CPU to perform operations

//实例1
char a,b,c;
char a=5;
//00000000 00000000 00000000 00000101
//00000101(截断后存储到a中)
char b=127;
//00000000 00000000 00000000 01111111
01111111(截断后存储到b中)
char a = b + c;
//00000000 00000000 00000000 00000101  a
//00000000 00000000 00000000 01111111  b
//00000000 00000000 00000000 10000100
//10000100(截断后存储到c中)
printf(“%d”,c)
//这里还是要整型提升
//11111111 11111111 11111111 10000100 补码
//10000000 00000000 00000000 01111011 反码
//10000000 00000000 00000000 01111010 原码
//%d是按照10进制的形式打印有符合的整数
/*可能会有人对这有疑惑11111111 11111111 11111111 10000100 补码
为什么左边全是1,其实是因为在整形提升时最高位补符号位*/
b和c的值被提升为普通整型,然后再执⾏加法运算。
加法运算完成之后,结果将被截断,然后再存储于a中

How to improve overall

  1. Signed integer promotion is promoted according to the sign bit of the variable's data type.
  2. Unsigned integer promotion, high bits filled with 0
//负数的整形提升
char c1 = -1;
变量c1的⼆进制位(补码)中只有8个⽐特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,⾼位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111

//正数的整形提升
char c2 = 1;
变量c2的⼆进制位(补码)中只有8个⽐特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,⾼位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//⽆符号整形提升,⾼位补0

Arithmetic conversion

If the operands of an operator are of different types, the operation cannot proceed unless one of the operands is converted to the type of the other . The following hierarchy is called ordinary arithmetic transformations

1.long double
2.double
3.float
4.unsigned long int
5.long int
6.unsigned int
7.int
//如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏
运算。
//比如int和double,因为int排在double后面,所以要将int转换为double类型再执行运算

Problem expression analysis

The following expressions conflict with mathematical calculation methods, so pay special attention to them.

Expression 1

//表达式的求值部分由操作符的优先级决定。
//表达式1
a*b + c*d + e*f

Many people will calculate a b, c d, e f at the same time because the priority is higher than +,
but the priority does not determine that the third * is executed earlier than the first +, because it can only be determined to be adjacent to it arithmetic operators
so the computer order of the expression might be:

1:a*b
2:c*d
3:a*b + c*d
4:e*f
5:a*b + c*d + e*f

But it's also possible

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

Expression 2

//表达式2
c + --c;

As above, the priority of the operator can only determine whether the operation of self-decrement – ​​is before the operation of +, but we have no way to know whether the acquisition of the left operand of the + operator is evaluated before or after the right operand, so The results are unpredictable and ambiguous
. For example:

intc=1;
c+--c

If the first c is 1, then c+ --c=1+0=1,
and if the first c is assigned after –c, then c+ --c=0+0=0,

so don’t write the code like this, otherwise it will end I can’t even figure out how the result came about.

Expression 3

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

Expression 3 test results in different compilers: results of illegal expression program
insert image description here

Expression 4

#include <sdtio.h>
int fun()
{
    
    
static int count = 1;
return ++count;
}
int main()
{
    
    
int answer;
answer = fun() - fun() * fun();
printf( "%d\n", answer);
return 0;
}

In the above code answer = fun() - fun() * fun(); we can only know from the priority of the operator:
multiplication is calculated first, and then subtraction, but the calling order of the functions cannot be determined by the priority of the operator Sure

Expression 5

//表达式5
#include <stdio.h>
int main()
{
    
    
int i = 1;
int ret = (++i) + (++i) + (++i);
printf("%d\n", ret);
printf("%d\n", i);
return 0;
}

When the first + in this code is executed, whether the third ++ will be executed is uncertain, because it is impossible to determine the first + and the third former depending on the priority and associativity of operators. The order of setting ++

Summarize

Even with the priority and associativity of operators, the expression we write may still not be able to determine the unique calculation path through the attributes of the operator. Then this expression is potentially risky. It is recommended not to write fancy expressions. style, otherwise you will be confused

Guess you like

Origin blog.csdn.net/2301_79178723/article/details/132363185