Detailed explanation of operators - C language

Table of contents

1. Classification of operators:

2. Arithmetic operators

3. Shift operator 

3.1 Left shift operator

3.2 Right shift operator

4. Bitwise operators 

5. Assignment operator 

6. Unary operators

6.1 Introduction to unary operators 

7. Relational Operators

8. Logical operators 

9. Conditional Operators 

10. Comma expressions 

11. Subscript references, function calls, and structure members 

12. Expression Evaluation 

12.1 Implicit type conversions 

12.2 Arithmetic conversions 

12.3 Properties of operators 


1. Classification of operators:

  算术操作符
  移位操作符
  位操作符
  赋值操作符
  单目操作符
  关系操作符
  逻辑操作符
  条件操作符
  逗号表达式
  下标引用、函数调用和结构成员

2. Arithmetic operators

                                  +   -  *  /  %

1. In addition to the % operator, several other operators can act on integers and floating-point numbers.
2.  For the / operator, if both operands are integers, integer division is performed. And as long as there are floating-point numbers, floating-point number division is performed.
3.  The two operands of the % operator must be integers. Returns the remainder after division

3. Shift operator 

<< left shift operator shifts the binary sequence to the left
>> right shift operator shifts the binary sequence to the right

Speaking of shift operators is about to talk about binary

There are three forms of binary bit representation of integers: original code complement code inverse code

The original and complement codes of positive integers are the same

The one's complement and complement of negative integers are to be calculated

sign bit 0 - indicates a positive number

            1 - indicates a negative number

Integers are stored in two's complement in memory

               int a = 5
原码 000000000000000000000000000000000101
反码 000000000000000000000000000000000101
补码 000000000000000000000000000000000101
                               int a = -5
原码 10000000000000000000000000000101
反码 11111111111111111111111111111010 (原码的符号位不变,其他位取反的就是补码)
补码 11111111111111111111111111111011  (反码+1就是补码)

3.1 Left shift operator

Left shift: It is to discard the left side of the binary sequence and add 0 to the right side

int main()
{
	int a = 5;
	int b = a << 1;
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

 program running result

int main()
{
	int a = -5;
	int b = a << 1;
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

program running result

Note: The values ​​printed by the compiler are all original codes 

Conversion Rules of Negative Number's Complement of Original Code and Complement Code

3.2 Right shift operator

Shift right into two

Arithmetic right shift: the right side is discarded, and the left side is filled with the original sign bit

Logical right shift: discard on the right, add 0 to the left 

Whether it is an arithmetic right shift or a logical right shift is up to the compiler

Note: For shift operators, do not shift negative bits, this is undefined by the standard  

4. Bitwise operators 

& //According to the (binary) bit and (as long as the corresponding binary bit has 0, it is 0, and only all 1s are 1) | //
According  to the (binary) bit or (as long as the corresponding binary bit has 1, it is 1, only All 0s are 0)
^ //Exclusive or by (binary) bits (the corresponding binary bits are 0, and different ones are 1)
Note: Their operands must be integers

int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;
	int d = a | b;
	int e = a ^ b;
	printf("%d\n", c);
	printf("%d\n", d);
	printf("%d\n", e);

	return 0;
}
00000000000000000000000000000011  -> 3的补码
11111111111111111111111111111011  -> -5的补码

(再次提醒,编译器打印出来的是原码,而正数原码反码补码相同)
00000000000000000000000000000011  -> 3&-5的结果 结果是3

(补码)
11111111111111111111111111111011  -> 3|-5的结果
10000000000000000000000000000101  (原码) 结果是-5

(补码)
11111111111111111111111111111000  -> 3^-5的结果
10000000000000000000000000001000  (原码) 结果是-8

program running result

A perverted interview question:

Cannot create a temporary variable (the third variable) to realize the exchange of two numbers

#include <stdio.h>
int main()
{
   int a = 10;
   int b = 20;
   a = a^b;
   b = a^b;
   a = a^b;
   printf("a = %d b = %d\n", a, b);
   return 0;
}

Beginners don't expect to know it, just know that there is such a method.

5. Assignment operator 

The assignment operator is a great operator that allows you to get a value that you were not happy with before. That is, you can reassign yourself.

int weight = 120;//体重
weight = 89;//不满意就赋值
double salary = 10000.0;
salary = 20000.0;//使用赋值操作符赋值

compound assignment operator 

+= -= *= /= %= >>= <<= &= |= ^=

For example: int x += 2 ; //x = x+2

6. Unary operators

6.1 Introduction to unary operators 

! Logical inverse operation
- negative value
+ positive value
& take
address sizeof operand type length (in bytes)
~ binary bitwise inversion of a number
-- preposition, postposition --
++ preposition, postfix ++
* indirection operator (dereference operator)
(type) cast 

In C language, 0 means false, non-zero means true

int num =10;
if(num)
{
   printf("hehe\n);
}

//!num 就是假 if语句不进入

1. sizeof (array name), the array name is not the address of the first element of the array, the array name represents the entire array, and the calculation is the size of the entire array. Except for this case, all array names represent the address of the first element of the array. 

 sizeof is an operator, not a function. It calculates the size of the memory occupied by the variable created by the type, and the unit is byte.

The expression in sizeof() does not participate in the calculation 

A nasty question about sizeof

#include <stdio.h>
int i;
int main()
{
    i--;
    if (i > sizeof(i))
    {
        printf(">\n");
    }
    else
    {
        printf("<\n");
    }
    return 0; 
}

Q: What will the program output?

Explanation: First, if the global variable is not initialized, it will be set to 0 by default, so the value of i is 0 at this time; and the sizeof operator, its return value is size_t, and size_t represents an unsigned number, here this The expression needs to perform arithmetic conversion (i > sizeof(i)), and the compiler will automatically convert the left i into unsigned integer data. The unsigned integer corresponding to -1 is a very large number, exceeding 4 or 8, so the final result is to print ">".

& takes address and * indirect access operator (dereference operator)

int main()
{
	//& 取地址操作符
	//* 解引用操作符(间接访问操作符)

	int a = 10;
	int* pa = &a;
	*pa = 20;//* - 解引用操作符
	//
	//*&a ==> a;
	return 0;
}

7. Relational Operators

> >= < <= !=  ==

have nothing to say 

8. Logical operators 

&& logical and
|| logical or

Logical AND The entire expression is true only if both left and right expressions are true

Logical or only if the left and right expressions are both false, the entire expression is false 

int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	//i = a++ && ++b && d++;

	i = a++ || ++b || d++;

	printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
	return 0;
}

Analysis: i = a++ || ++b || d++; a++ uses a first, then ++, ay starts at 0, goes down, ++b, first b++, in use, and the value of the entire expression If it is already true, the following d++ will not be executed, so the running result of the program is 1 , 3 , 3 , 4.

9. Conditional Operators 

exp1 ? exp2 : exp3

If statement 1 is true, the result of the expression is statement 2, otherwise it is statement 3 

int main()
{
	int a = 3;
	int b = 5;
	int m = (a > b ? a : b);
	printf("%d\n", m);
	return 0;
}

10. Comma expressions 

Comma expressions are multiple expressions separated by commas.
Comma expressions are executed sequentially from left to right. The result of the entire expression is the result of the last expression 

int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, a, b = a + 1);
	printf("a=%d b=%d\n", a, b);
	printf("%d\n", c);
	return 0;
}

11. Subscript references, function calls, and structure members 

1. [ ] subscript reference operator

Operand: an array name + an index value

int arr[10];//Create an array
arr[9] = 10;//Practical subscript reference operator.
The two operands of [ ] are arr and 9

2. ( ) The 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.

Note: there can be no parameters

3. Access a member of a structure
 . Structure. Member name
-> Structure pointer -> Member name 

#include <stdio.h>
struct Stu
{
   char name[10];
   int age;
   char sex[5];
   double score;

};

void set_age1(struct Stu stu)
{
   stu.age = 18;
}

void set_age2(struct Stu* pStu)
{
   pStu->age = 18;//结构成员访问
}

int main()
{
   struct Stu stu;
   struct Stu* pStu = &stu;//结构成员访问
   stu.age = 20;//结构成员访问
   set_age1(stu);
   pStu->age = 20;//结构成员访问
   set_age2(pStu);
   return 0;
}

12. Expression Evaluation 

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

12.1 Implicit type conversions 

C's integer arithmetic operations are always performed with at least the precision of the default integral type. To achieve this precision, character and short integer operands in expressions are converted to plain integer types before use, a conversion known as integer promotion.


The significance of integer promotion :
the integer operation of the expression must be executed in the corresponding computing 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 byte length of the CPU. The length of the general-purpose registers. Therefore, even if the addition of two char types is actually performed by the CPU, it must first be converted to the standard length of the integer operand in the CPU. It is difficult for a general-purpose CPU (general-purpose CPU) to directly add two 8-bit bytes directly (although there may be such byte addition instructions in machine instructions). 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 for calculation. 

char a,b,c;
...
a = b + c;

The values ​​of b and c are promoted to normal integers before the addition operation is performed.

After the addition operation is complete, the result is truncated before being stored in a.

How to carry out overall improvement?

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

//负数的整形提升
char c1 = -1;
变量c1的二进制位(补码)中只有8个比特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111
//正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//无符号整形提升,高位补0

give two examples 

int main()
{
	char c1 = 3;
	//首先要进行整型提升
	//00000000000000000000000000000011
	//00000011 - c1
	char c2 = 127;
	//首先要进行整型提升
	//00000000000000000000000001111111
	//01111111 - c2
	

	char c3 = c1 + c2;
	//00000000000000000000000000000011
	//00000000000000000000000001111111
	//00000000000000000000000010000010
	// 这里要发生截断
	//10000010 - c3
	// 此时c1是字符型,但我们是要以整型形式打印,所以还要进行整型提升。
	//11111111111111111111111110000010 补码
	//11111111111111111111111110000001 反码 
	//10000000000000000000000001111110 原码
	//-126
	
	printf("%d\n", c3);//
	
	return 0;
}
int main()
{
   char a = 0xb6;
   short b = 0xb600;
   int c = 0xb6000000;
   if(a==0xb6)
     printf("a");
   if(b==0xb600)
     printf("b");
   if(c==0xb6000000)
     printf("c");
   return 0;
}

In the example, a and b need to be plasticized and upgraded, but c does not need to be plasticized and upgraded. After a and b are plasticized and promoted, they become negative numbers, so the result of the expression a==0xb6, b==0xb600 is false, but c does not happen If the integer is improved, the result of the expression c==0xb6000000 is true.
The result output by the program is: c

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

As long as c participates in the expression operation, the plastic promotion will occur, and the expression +c will be promoted, so sizeof(+c) is 4 bytes. The
expression -c will also undergo plastic promotion, so sizeof(-c ) is 4 bytes, but sizeof(c) is 1 byte. 

12.2 Arithmetic conversions 

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 conversion

long double
double
float
unsigned long int
long int
unsigned int
int

If the type of an operand is lower in the above list, it must first be converted to the type of the other operand before performing the operation

12.3 Properties of operators 

There are three factors that affect the evaluation of complex expressions.
1. Priority of operators (must be adjacent operators)
2. Associativity of operators
3. Whether to control the order of evaluation.
Which of two adjacent operators is executed first? Depends on their priorities. If both have the same priority, it depends on their associativity.

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

For example, the code produces different results under several compilation environments.

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

Guess you like

Origin blog.csdn.net/m0_63562631/article/details/125821487