Fifth stop: operator

1. Introduction to various operators.

2. Expression evaluation

catalogue

1. Operator classification:

2. Arithmetic operator

3. Shift operator

3.1 shift left operator

3.2 shift right operator

4. Bitwise operator

5. Assignment operator

6. Monocular operator

6.1 introduction to monocular operators

6.2 sizeof and array

7. Relational operators

8. Logical operators

9. Conditional operator

10. Comma expression

11. Subscript references, function calls and structure members

1. [] subscript reference operator

2. () function call operator

3. Visit members of a structure

12. Expression evaluation

12.1 implicit type conversion

12.2 arithmetic conversion

12.3 properties of operators

1. Operator classification:

arithmetic operator

Shift operators

Bitwise operators

Assignment operator

unary operator

Relational operator

Logical operator

Conditional Operator

comma expression

Subscript references, function calls, and structure members

2. Arithmetic operator

+ - * / %

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, perform integer division. As long as there are floating-point numbers, it is floating-point division.

3. The two operands of the% operator must be integers. Returns the remainder after division.

3. Shift operator

Moving is binary complement

< < shift left operator

>>Shift right operator

Note: the operands of shift operators can only be integers.

3.1 shift left operator

Shift rule: discard on the left and fill 0 on the right

Move left, discard left, fill zero right
 Integers are stored in memory as binary sequences of complements
//int main()
//{
//	//There are three binary representations of integers
//	//Inverse complement of original code
//	//The original inverse complement of positive integers is the same
//	//The original inverse complement of a negative integer needs to be calculated
//
//	int a = 5;// 5 (5)2=0101;
//	//Because a is an integer, 4 bytes and 32 bits
//	//0000 0000 0000 0101 original code
//	//0000 0000 0000 0101 inverse code
//	//0000 0000 0101 complement
//
//	int c = -5;
//	//-5;
//	//Original code of 1000 0000 0101 - 5
//	//1111 1111 1111 1111 1111 1111 1111 1010 - 5
//	//From the original code to the inverse code, the sign bit remains unchanged, and other bits are reversed by bit
//	//1111 1111 1111 1111 1111 1111 1111 1011 - 5 Complement
//	//From inverse code to complement code, you need to add one
//
//	int b = a << 1;// A the essence is invariable
//	//What moves is the complement of binary bits;
//	//000 0000 0000 01010 complement
//	int d = c << 1;
//	//111 1111 1111 1111 1111 1111 1111 10110 - 5 complement after left shift
//	//111 1111 1111 1111 1111 1111 1111 10101 - 5 inverse code after left shift
//	//100 0000 01010 - 5 original code shifted left
//	//-10
//
//	printf("%d\n", a);//5
//	printf("%d\n", b);//10
//	printf("%d\n", d);//-10
//	//The printed value is the original code
//	return 0;
//}

3.2 shift right operator

Shift rule:

First, there are two kinds of shift right operations:

1. The logical shift is filled with 0 on the left and discarded on the right

2. The left side of arithmetic shift is filled with the sign bit of the original value, and the right side is discarded

>>When the current compiler shifts to the right, arithmetic shift to the right is adopted
>>Whether arithmetic shift right or logical shift right depends on the compiler!!!
 
The shift right operator has two rules:
1.Arithmetic shift right: discard the right and fill the original symbol bit on the left
2.Logical shift right: discard on the right and fill zero on the left
//int main()
//{
//	int a = 5;
//	//0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
//	//5 is a positive number, the sign bit is 0, and the arithmetic right shift or logical right shift are the same
//	int b = a >> 1;
//	//00000 0000 0000 0000 0000 010 5 right shifted complement
//
//	int c = -5;
//	//1111 1111 1111 1111 1111 1111 1111 1011 - 5 Complement
//	int d = c >> 1;
//	//11111 1111 1111 1111 1111 1111 1111 101 - 5 complement after right shift
//	//11111 1111 1111 1111 1111 1111 1111 100 - 5 reverse code after right shift
//	//10000 0000 0000 0000 0000 011 - 5 original code after right shift
//	printf("%d\n", a);//5
//	printf("%d\n", b);//2
//	printf("%d\n", c);//-5
//	printf("%d\n", d);//-3
//	return 0;
//}

warning ⚠ : For shift operators, do not move negative digits, which is not defined in the standard.

For example:

int num = 10;num>>-1;//error

4. Bitwise operator

Bitwise operators are:

&/ / bitwise AND

|/ / bitwise OR

^/ / bitwise XOR

//There are three kinds of bitwise operators:
//1. & Press (binary) bit and / / A & B -- binocular operator
//2. | by (binary) bit or 		   // & A -- monocular operator	
//3. ^ exclusive or by (binary) bit
int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;
	//0000 0000 0000 0000 0011 3 Complement
	//1111 1111 1111 1111 1111 1111 1111 1011 - 5 Complement
	//Bitwise and - if two are 1 at the same time, the result is 1;
	//0000 0000 0000 0011 complement of 3 & - 5
	printf("%d\n", c);//3

	int d = a | b;
	//0000 0000 0000 0000 0011 3 Complement
	//1111 1111 1111 1111 1111 1111 1111 1011 - 5 Complement
	//Bitwise and - if one is 1, the result is 1;
	//1111 1111 1111 1111 1111 1111 1011 3 | - 5 Complement
	//1000 0000 0101 original code
	printf("%d\n", d);//-5

	int e = a ^ b;
	//0000 0000 0000 0000 0011 3 Complement
	//1111 1111 1111 1111 1111 1111 1111 1011 - 5 Complement
	//Bitwise XOR, 0 for the same and 1 for the different;
	//1111 1111 1111 1111 1111 1111 1111 1000 3 ^ - 5 Complement
	//Original code of 1000 million 3 ^ - 5
	printf("%d\n", e);//-8
	return 0;
}

//summary
//a ^ a = 0;   The two corresponding binaries are exactly the same, and the XOR is 0;
//0 ^ a = a;  
//For example: the complement of 0000 0000 0000 0000 0000 0000 0
//      1111 1111 1111 1111 1111 1111 1111 1011 - 5 Complement
//0 ^ - 5 1111 1111 1111 1111 1111 1111 1011 still - 5  
//Array arr1[100] = {1, 2, 3, 4, 5}
//Array arr2[100] = {1, 2, 3, 4}
//There are two arrays. The number of elements in the array is unknown, but the array elements
//They all appear in pairs. Only one element appears once. Find out
//A number that appears only once
//answer:
// arr1[100] XOR arr2[100]
//Because the XOR result of the same two elements is 0;
//And 0 and non-0 XOR result is itself

Note: their operands must be integers.

A perverse interview question:

//You cannot create a temporary variable to exchange two integers
int main()
{
	int a = 3;
	int b = 5;
	printf("a = %d,b = %d\n", a, b);
	//a = a + b;
	//b = a - b;
	//a = a - b;
	//If the values of a and B are too large, the addition will overflow
	a = a ^ b;//011 ^ 101 = 110 
	b = a ^ b;//110 ^ 101 = 011
	//b = a ^ b - brought in - b = a ^ b ^ b = a ^ 0 = a
	a = a ^ b;//110 ^ 011 = 101
	// a = a ^ b ^ a = 0 ^ b = b
	printf("a = %d,b = %d\n", a,b);
	return 0;
}
//practice
//Find the number of an integer stored in binary 1 in memory
//5
//0000 0000 0000 0000 0000 0000 0000 0101
//Bitwise AND
//0000 0000 0000 0000 0000 0000 0000 0001
//=0000 0000 0000 0000 0000 0000 0000 0001     1
//5&1==1
//Shift right
int main()
{
	int i = 0;
	int count = 0;
	int num = 0;
	scanf("%d", &num);
	int sz = sizeof(num) * 8;
	for (i = 0; i < 32; i++)
	{
		if (((num >>i)& 1) == 1)
			count++;
	}
	printf("%d\n", count);
	return 0;
}

5. Assignment operator

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

Compound assignor

+

=

-=

*=

/=

%=

>>=

<<=

&=

|=

^=

These operators can be written as compound effects

//Assignment operator
//int main()
//{
//	int a = 10;
//	int x = 0;
//	int y = 20;
//	a = x = y + 1;
//	a = a + 2;
//	a += 2;
//	printf("%d %d\n", a, x);
//	return 0;
//}

6. Monocular operator

6.1 introduction to monocular operators

! Logical reverse operation

-Negative value

+Positive value

&Take address

Type length of sizeof# operand in bytes

~The binary bit negation of a number

--Front and rear--

++Front and rear++

*Indirect access operator (dereference operator)

(type) cast

//unary operator 
//There is no type of true or false before C99 in C language
//Boolean types are introduced in C99
//#include<stdbool.h>
//int main()
//{
//	_Bool flag1 = false;
//	bool flag2 = true;
//	if (flag2)
//	{
//		printf("hehe\n");
//	}
//	//int num = 10;
//	//if (num)
//	//{
//
//	//}
//	//if (!num)//num is false, do something
//	//{
//
//	//}
//	return 0;
//}
struct S
{
	char name[20];
	int age;
};
int main()
{
	//&-- Address fetching operator
	//*- dereference operator (indirect access operator)

	int a = 10;
	int* pa = &a;
	*pa = 20;//dereference operator 
	int arr[10] = { 0 };
	&arr;//Get the address of the array. The address of the array should be put in [array pointer]
	struct S s = { 0 };
	struct S* ps = &s;
	return 0;
}
// ~Reverse bit by bit
int main()
{
	int a = 0;
	//0000 0000 0000 0000 0000 0000 0000 0000
	//1111 1111 1111 1111 1111 1111 1111 1111 1111 ~a's complement
	//Original code of 1000 0000 0001 ~a
	printf("%d\n", ~a);//-1
	return 0;
}

6.2 sizeof and array

//struct S
//{
//	char name[20];
//	int age;
//};
//int main()
//{
//	//&- Operator address
//	//*- dereference operator (indirect access operator)
//
//	int a = 10;
//	int* pa = &a;
//	*pa = 20;// dereference operator 
//	// *&a ==>a
//	int arr[10] = { 0 };
//	&arr;// Get the address of the array. The address of the array should be put in [array pointer]
//	struct S s = { 0 };
//	struct S* ps = &s;
//	return 0;
//}

//sizeof()
//Calculate the amount of memory occupied by variables created by the type
int main()
{
	//int a = 10;
	//printf("%d\n", sizeof a);
	sizeof Is an operator, is c Keyword of language, not function
	//printf("%d\n", sizeof(a));
	//printf("%d\n", sizeof(int));

	/*int arr[10] = { 0 };
	printf("%u\n", (unsigned int)sizeof(arr));*/

	int a = 10;
	short s = 0;
	printf("%d\n",(unsigned int)sizeof(s = a + 2));//2
	//The expression in sizeof() does not participate in the calculation;
	//sizeof() is processed during compilation
	printf("%d\n", s);//0
	return 0;
}
//sizeof() and array
void test1(int arr[])
{
	printf("%d\n", sizeof(arr));//4
}
void test2(char* ch)
{
	printf("%d\n", sizeof(ch));//4
}
int main()
{
	int arr[10] = { 0 };
	char ch[10] = { 0 };
	printf("%d\n", sizeof(arr));//40
	printf("%d\n", sizeof ch);//10
	test1(arr);
	test2(ch);
	return 0;
}
// ~Reverse bit by bit
int main()
{
	//int a = 0;
	0000 0000 0000 0000 0000 0000 0000 0000
	1111 1111 1111 1111 1111 1111 1111 1111 ~a Complement of
	1000 0000 0000 0000 0000 0000 0000 0001 ~a Original code of
	//printf("%d\n", ~a);//-1

	int a = 11;
	//0000 0000 0000 0000 1011 11 complement
	//0000 0000 0000 0000 0000 0000 0000 0100   11|4
	//0000 0000 0000 0000 0000 0000 0000 1111   15
	//0000 0000 0000 0000 0000 0000 0000 0001   1
	// 1<<2;
	a |= (1<<2);
	printf("%d\n", a);//15
	//a ^= (1 << 2);
	a &= (~(1 << 2));
	printf("%d\n", a);//11
	return 0;
}

7. Relational operators

Relational operator

>

>=

<

<=

!= Used to test "inequality"

==Used to test "equal"

int main()
{
	//The comparison is not the string, but the address of the first string
	if ("abcdef" == "abbq")
	{

	}
	return 0;
}

These relational operators are relatively simple and have nothing to say, but we should pay attention to some pitfalls in the use of operators.

Warning:

In the process of programming = = and = are written incorrectly, resulting in errors.

8. Logical operators

What are the logical operators

&&Logic and

||Logical or

Distinguish logical and bitwise AND

Distinguish between logical or and bitwise OR

1&2----->0                        1&&2---->1

1|2----->3                          1||2---->1

#include <stdio.h>
int main()
{
	int i = 0,a=0,b=2,c =3,d=4;
	//i = a++ && ++b && d++;//a=1,b=2,c=3,d=4,i=1
	//For logic and operators, the left lvalue is false, and the rest will not be calculated
	
	//If int a = 1;
	//i = a++ && ++b && d++;//a=2;b=3;c=3;d=5

	i = a++||++b||d++;//a=1;b=3;c=3;d=4
	//a use first and then + +; b + + first, then use
	//I = 0 | 3 a true is true, and it is not calculated later
	
	//If int a = 1;
	//i = a++ || ++b || d++;//a=2;b=2;c=3;d=4

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

9. Conditional operator

exp1 ? exp2 : exp3

10. Comma expression

exp1, exp2, exp3, ...expN

Comma expressions are multiple expressions separated by commas.

Comma expression, executed 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, b = a + 1); //(0,a=12,b=13)
	printf("%d\n", c);//13
	return 0;
}

11. Subscript references, function calls and structure members

1. [] subscript reference operator

Operands: an array name + an index value ----------- has two operands arr and 4

//Subscript reference operator []
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", arr[4]);//5   //arr[4]-->*(arr+4)
	printf("%d\n", 4[arr]);//5   
	//arr
	//arr[4] = 5;  // [] is the subscript reference operator
	//
	return 0;
}

It can be seen that [] is equivalent to an operator, and arr and 4 are only two operands. For example, a+b and b+a are equivalent

2. () function call operator

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

//() function call operator
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int ret = Add(2, 3);//The operands are: Add, 2, 3
	printf("%d\n", ret);//5
	return 0;
}

3. Visit members of a structure

. structure member name

->Structure pointer - > member name

//Struct member access operator
#include<string.h>
typedef struct 
{
	char name[20];
	int age;
	float score;
}stu;
//struct stu
//{
//	char name[20];
//	int age;
//	float score;
//};
void print1(stu s)
{
	printf("name:%s age:%d score:%f\n", s.name, s.age, s.score);

}
void print2(stu* pc)
{
	//printf("name:%s age:%d score:%f\n", (*pc).name, (*pc).age, (*pc).score);
	// The struct member operator takes precedence over the dereference operator
	printf("name:%s age:%d score:%f\n", pc->name, pc->age, pc->score);

}
int main()
{
	stu s = { "Zhang Shan",20,90.5f };
	//s.name = "Zhang Fengfeng"// The array name is an address and cannot be changed directly
	strcpy(s.name,"Zhang Sanfeng");
	//scanf("%s", s.name);
	print1(s);
	print2(&s);
	return 0;
}

12. Expression evaluation

The order in which expressions are evaluated is partly determined by the priority and associativity of operators.

Similarly, the operands of some expressions may need to be converted to other types during evaluation.

12.1 implicit type conversion

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. The byte length of the operand of the integer operator (ALU) in the CPU is generally the byte length of int and the length of the general register of the CPU.

Therefore, even if the two char types are added, they actually have to be converted to the standard length of integer operands in the CPU when executed by the CPU.

General purpose CPU (general purpose CPU) is difficult to directly realize the direct addition of two 8-bit bytes (although there may be such byte addition instructions in machine instructions). Therefore, all integer values whose length may be less than int in the expression must be converted to int or unsigned int before being sent to the CPU for operation.

How to carry out the overall improvement?

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

int main()
{
	char c1 = 3;
	//Integer is stored in character type, and 4 bytes are stored in 1 byte, which will be truncated
	//0000 0000 0000 0000 0000 0000 0000 0011
	//c1 = 0000 0011
	char c2 = 127;
	//0000 0000 0000 0000 0000 0000 0111 1111
	//c2 = 0111 1111
	char c3 = c1 + c2;
	//When c1 and c2 are calculated, integer lifting is performed first before adding
	//c1 = 0000 0000 0000 0000 0000 0000 0000 0010
	//c2 = 0000 0000 0000 0000 0000 0000 0111 1111
	//c1+c2 = 0000 0000 0000 0000 0000 0000 1000 0010
	//c3 = c1 + c2; Truncate
	//c3 = 1000 0010
	printf("%d", c3);
	//Printing is shaping again, and integer upgrading is carried out
	//1111 1111 1111 1111 1111 1111 1000 0010; Complement
	//1000 0000 0000 0000 0000 0000 0111 1110; Original code = - (2 ^ 7-1)
	return 0;
}
int main()
{
	char a = 0xb6;
	//1011 0110
	short b = 0xb600;
	//1011 0110 0000 0000
	int c = 0xb6000000;
	//1011 0110 0000 0000 0000 0000 0000 0000
	if (a == 0xb6)
	//A is a character type. If it is converted to an integer type, integer promotion is required
	//1111 1111 1111 1111 1111 1111 1011 0110  a
	//0000 1011 0110 / / unequal
	{
		printf("a");
	}
	if (b == 0xb600)
	//b is a short integer. Compared with integer, integer promotion is required
	//1111 1111 1111 1111 1011 0110 0000 0000 b
	//0000 1011 0110 0000 / / unequal
	{
		printf("b");
	}
	if (c == 0xb6000000)
	//c is integer. Integer is compared with integer data, and integer promotion is not required
	{
		printf("c");
	}
	return 0;
	//Print c
}
int main()
{
	char c = 1;
	printf("%u\n", sizeof(c));//1

	printf("%u\n", sizeof(+c));//4
	printf("%u\n", sizeof(-c));//4
	//A positive sign and a negative sign indicate that integer promotion is required for the operation of the expression
	return 0;
}

12.2 arithmetic conversion

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

Bottom up conversion

If the type of an operand ranks low in the above list, it must first be converted to the type of another operand and then perform the operation.

Warning:

But the arithmetic conversion should be reasonable, otherwise there will be some potential problems.

float f = 3.14;

int num = f;// Implicit conversion, there will be precision loss

12.3 properties of operators

There are three factors that affect the evaluation of complex expressions.

1. Operator priority

2. Associativity of operators

3. Whether to control the evaluation sequence.

Which of the two adjacent operators should be executed first?         

Depends on their priorities. If the two have the same priority, it depends on their combination.

Operator precedence

 

Some problem expressions

//The evaluation part of the expression is determined by the priority of the operator.

//Expression 1

a*b + c*d + e*f

Note: when calculating code 1, because * has a higher priority than +, it can only be guaranteed that * is calculated earlier than + but the priority does not determine that the third * is executed earlier than the first +.

Therefore, the computer order of expressions may be:

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

//Expression 2

c + --c;

notes:

As above, the priority of the operator can only determine whether the operation of self subtraction is in front of the operation of + but we have no way to know whether the left operand of + operator is evaluated before or after the right operand, so the result is unpredictable and ambiguous.

//Code 3 - illegal expression
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 programs

Value compiler

—128        Tandy 6000 Xenix 3.2

—95          Think C 5.02(Macintosh)

—86          IBM PowerPC AIX 3.2.5

- 85# sun SPARC CC (K & C compiler)

—63          gcc,HP_UX 9.0,Power C 2.0.0

4. Sun SPARC ACC (K & C compiler)

21             Turbo C/C++ 4.5

22              FreeBSD 2.1 R

30              Dec Alpha OSF1 2.0

36              Dec VAX/VMS

42              Microsoft C 5.1

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

Is there a real problem with this code?

something the matter!

Although the results are the same on most compilers. However, the above code answer = fun() - fun() * fun(); in

We can only know from the priority of operators: multiply first and then subtract.

The call order of functions cannot be determined by the priority of operators.

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

Keywords: network Network Protocol p2p

Added by conor.higgins on Thu, 03 Mar 2022 16:28:34 +0200