C language learning notes - P14 (operator explanation < 2 > + illustration + problem example)

catalogue

Preface: ● due to the limited level of the author, it is inevitable that there are fallacies in the article. Please correct the slang and sincerely hope to give advice!

                                                                      —— By author: Xinxiao · old friend

6. Monocular operator

six point one   sizeof and arrays

  Note:

1.test (test in the main function) passes the address of the first element!

2.test (test defined by the function) is an array, but it is essentially a pointer! Therefore, test (test defined by the function) can be written as an array or a pointer! int arr[ ] ——int *arr. Similarly, char ch [] -- char *ch.

3. The size of sizeof calculation pointer is not affected by type! The pointer size is 4 bytes (32-bit machine) or 8 bytes (64 bit machine)

X86-32-4

X64-64-8

4. About (4), the output is 4: because sizeof calculates the size of the pointer, char is the size of the character (the space size pointed to by char), which is 1 byte, but the pointer address (32-bit or 64 bit binary sequence) is 4 bytes!

  7. Relational operators

  8. Logical operators

9. Conditional operator

   10. Comma expression

  11. Subscript references, function calls, and structure members

11.1. [] subscript reference operator operand: an array name + an index value

1. [] is the subscript reference operator. Arr and 7 are operands  

2.arr[7]--> *(arr+7) --> *(7+arr)-->7[arr]  

  11.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.

() - function call operator

  11.3. Access to members of a structure

  12. Expression evaluation

12.1 implicit type conversion

Significance of integer lifting:

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

12.2 arithmetic conversion

  12.3 operator properties

 

preface:
● due to the limited level of the author, it is inevitable that there are fallacies in the article. Please correct the slang, and sincerely hope to give advice!

                                                                      —— By author: Xinxiao · old friend

6. Monocular operator

!           Logical reverse operation
-           negative
+           positive
&           Get address
sizeof      The type length of the operand in bytes
~           Bitwise negation of a number
--          Front and rear--
++          Front and rear++
*           Indirect access operator(dereference operator )
(type)       Cast type

  In fact, we have seen about sizeof before. We can find the space occupied by variables (types).

Pre + +: first + +, then use

#include <stdio.h>

int main()
{
	int a = 10;
	int b = ++a;   Front++,before++,Post use
	printf("a=%d b=%d\n", a, b);
	return 0;
}

   Post + +: use first, then++

#include <stdio.h>

int main()
{
	int a = 10;

	//int b = ++a;    Pre + +, first + +, then use
	int b = a++;     Post++,Use first, then++
	printf("a=%d b=%d\n", a, b);
	
	return 0;
}

int main()
{
	int a = 10;

	//int b = ++a;// Pre + +, first + +, then use
	//int b = a++;// Post + +, use first, and then++
	//printf("a=%d b=%d\n", a, b);

	printf("%d\n", ++a);
	return 0;
}

int main()
{
	int a = 10;

	//int b = ++a;// Pre + +, first + +, then use
	//int b = a++;// Post + +, use first, and then++
	//printf("a=%d b=%d\n", a, b);
	//printf("%d\n", ++a);
	printf("%d\n", a++);
	return 0;
}

 

 --  similar:

 

 ++ And -- incorrect use of the compiler will not compile correctly!

  X-shell - Linux teaching demonstration machine:

 

  Cast type:

int main()
{
	//int a =  3.14;        3.14 - double -> int a
	int a = (int)3.14;
	printf("%d\n", a);
	return 0;
}

                                                                                                  —— By author: Xinxiao · old friend

int main()
{
	//int a = 10;
	int* p = &a;  //This is when you create the p variable
	//(int*) p = &a;// Err write this way to cast without p variable. Error!
	//int a = (int)3.14;
	//int a = int(3.14);//err
	return 0;
}

#include <stdio.h>
int main()
{
 int a = -10;
 int *p = NULL;
 printf("%d\n", !2);
 printf("%d\n", !0);
 a = -a;
 p = &a;
 printf("%d\n", sizeof(a));
 printf("%d\n", sizeof(int));
 printf("%d\n", sizeof a);//Is that all right?
 printf("%d\n", sizeof int);//Is that all right?
 return 0;
}

 

 

 

six point one   sizeof and arrays

void test1(int arr[])
{
	printf("%d\n", sizeof(arr));//(2)
}
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));//(1)
	printf("%d\n", sizeof(ch));//(3)
	test1(arr);
	test2(ch);
	return 0;
}

  Note:

1.test (test in the main function) passes the address of the first element!

2.test (test defined by the function) is an array, but it is essentially a pointer! Therefore, test (test defined by the function) can be written as an array or a pointer! int arr[ ] ——int *arr. Similarly, char ch [] -- char *ch.

3. The size of sizeof calculation pointer is not affected by type! The pointer size is 4 bytes (32-bit machine) or 8 bytes (64 bit machine)

X86-32-4

X64-64-8

4. About (4), the output is 4: because sizeof calculates the size of the pointer, char is the size of the character (the space size pointed to by char), which is 1 byte, but the pointer address (32-bit or 64 bit binary sequence) is 4 bytes!

                                                                                                  —— By author: Xinxiao · old friend

  7. Relational operators

>
>=
<
<=
!=      Used to test "inequality"
==      Used to test equality

  Warning: in the process of programming = = and = are written incorrectly, resulting in errors!

int main()
{
	int a = 10;
	if (a==5)
	{
		printf("hehe\n");
	}
	else
	printf("a Not equal to 5!\n");
	return 0;
}

  The position of printf affects the output!

int main()
{
	int a = 10;
	if (a=5)
	{
		printf("hehe\n");
	}
	else
	printf("a Not equal to 5!\n");
	return 0;
}

int main()
{
	int a = 10;
	if (5=a)
	{
		printf("hehe\n");
	}
	else
	printf("a Not equal to 5!\n");
	return 0;
}

int main()
{
	int a = 10;
	if (5==a)      Recommended code habits
	{
		printf("hehe\n");
	}
	else
	printf("a Not equal to 5!\n");
	return 0;
}

 

 

                                                                                           —— By author: Xinxiao · old friend

  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

  

int main()
{
	int age = 0;
	scanf("%d", &age);
	if (0 < age < 18)   Wrong writing, wrong logic!
	{
		printf("under age\n");
	}
	return 0;
}

 

                                                                                                         —— By author: Xinxiao · old friend    

int main()
{
	int age = 0;
	scanf("%d", &age);
	//If (0 < age < 18) / / incorrect writing
	if (age>0&&age < 18)  //Correct writing
	{
		printf("under age\n");
	}
	else
	{
		printf("Adult\n");
	}
	return 0;
}

int main()
{
	int month = 4;//1~12 
	if (month < 1 || month>12)
	{
		printf("Correct range!\n");
	}
	else 
	{
		printf("Range error!\n");
	}
	return 0;
}

Characteristics of logic and and or:

Example:

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\n d = %d\n", a, b, c, d);
    return 0;
}
//What is the result of the program output?

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

    i = a++ && ++b && d++;
    //i = a++||++b||d++;
    printf(" a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d);
    return 0;
}
//What is the result of the program output?

 

int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    //int i = 0, a = 1, b = 2, c = 3, d = 4;
    
    //i = a++ && ++b && d++;
    i = a++||++b||d++;  //Logical or
    printf(" i=%d\n", i);
    printf(" a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d);
    return 0;
}

int main()
{
    //int i = 0, a = 0, b = 2, c = 3, d = 4;
    int i = 0, a = 1, b = 2, c = 3, d = 4;
    
    //i = a++ && ++b && d++;
    i = a++||++b||d++;  //Logical or
    printf(" i=%d\n", i);
    printf(" a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d);
    return 0;
}

 

9. Conditional operator

exp1 ? exp2 : exp3

  practice:

1.
if (a > 5)
        b = 3;
else
        b = -3;
What is it like to convert to a conditional expression?

b=(a>5? 3: -3);

   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 = 10;
	int b = 20;
	int max = 0;
	
	if (a > b)
		max = a;
	else
		max = b;

	//Conditional Operator 
	//max = (a > b ? a : b);
	printf("%d\n", max);
	re

//Code 3
a = get_val();
count_val(a);
while (a > 0)
{
  //Business processing
        a = get_val();
        count_val(a);
}

If you use a comma expression, override:
while (a = get_val(), count_val(a), a>0)
{
         //Business processing
}

  11. Subscript references, function calls, and structure members

11.1. [] subscript reference operator operand: an array name + an index value

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

1. [] is the subscript reference operator. Arr and 7 are operands  

2.arr[7]--> *(arr+7) --> *(7+arr)-->7[arr]
  

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

                                                                                                          —— By author: Xinxiao · old friend

  11.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.

void test()
{
	printf("hehe\n");
}
int Add(int x, int y)
{
	return x + y;
	printf("%d\n",x+y);
}
int main()
{
	test();                    () - function call operator 
	int ret = Add(2, 3);	
	printf("%d\n", ret);
	return 0;
}

() - function call operator

void test()
{
	printf("hehe\n");
}

int main()
{
	test();       //() - function call operator
	return 0;
}

 

#include <stdio.h>
 void test1()
 {
 printf("hehe\n");
 }
 void test2(const char *str)
 {
 printf("%s\n", str);
 }
 int main()
 {
 test1();              Utility () as a function call operator.
 test2("hello bit.");  Utility () as a function call operator.
 return 0;
 }

  11.3. Access to members of a structure

.   structural morphology.member name
->  Structure pointer->member name

                                                                                           —— By author: Xinxiao · old friend                 

struct Stu
{
	char name[20];
	int age;
	double score;
};

int main()
{
	struct Stu s = {"zhangsan", 20, 85.5};
	//.
	printf("%s %d %.1lf\n", s.name, s.age, s.score);          Structure variable.Structure member
	//->
	struct Stu * ps = &s;
	printf("%s %d %.1lf\n", (*ps).name, (*ps).age, (*ps).score);
	printf("%s %d %.1lf\n", ps->name, ps->age, ps->score);    Structure pointer->Structure member

	return 0;
}

 

 

#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;//Structure member access
}

int main()
{
 struct Stu stu;
 struct Stu* pStu = &stu;   Structure member access

 stu.age = 20;              Structure member access
 set_age1(stu);

 pStu->age = 20;            Structure member access
 set_age2(pStu);
 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.  

int main()
{
	char a = 5;
	char b = 126;
	char c = a + b;
	printf("%d\n", c);
	return 0;
}

sizeof(char) and sizeof (short) are both smaller than sizeof (int)  

 

                                                                                                          —— By author: Xinxiao · old friend

int main()
{
	char a = 5;
	//truncation
	//00000000000000000000000000000101
	//00000101 char type: one byte, 8 bit s

	char b = 126;
	//00000000000000000000000001111110
	//01111110
	//integral promotion 
	//00000000000000000000000000000101 - a
	//00000000000000000000000001111110 - b
	//Add after lifting
	//00000000000000000000000010000011
	//10000011 - c
	//When a and b are added, a and b are both char types
	//The expression evaluates to the value that is about to be raised
	//
	char c = a + b;
	//10000011 - if the C sign bit is 1, 1 is added during promotion
	//11111111111111111111111110000011 - complement
	//11111111111111111111111110000010
	//10000000000000000000000001111101 -> -125
	printf("%d\n", c);//?

	return 0;
}


 

Significance of integer lifting:

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 they can be sent to the CPU for operation.
Example 1

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

  The values of b and c 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 a.

How to carry out overall improvement?

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

1. Shaping and lifting of negative numbers
char c1 = -1;
There are only 8 bits in the binary bit (complement) of variable c1:
1111111
Because char is a signed char
Therefore, when shaping and lifting, the high supplementary symbol bit is 1
The result of the promotion is:
11111111111111111111111111111111

2. Shaping and lifting of positive numbers
char c2 = 1;
There are only 8 bits in the binary bit (complement) of variable c2:
00000001
Because char is a 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:

Example 1
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 example 1, a and B need shaping and lifting, but c does not need shaping and lifting
  a. B after shaping and lifting, it becomes a negative number,
Therefore, the result of expressions a = = 0xb6 and B = = 0xb600 is false,
But c there is no plastic improvement,
Then the result of expression c==0xb6000000 is true  
The output of the program is: c

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

  In example 2, as long as c participates in the expression operation,
The expression + c will be raised,
So sizeof(+c) is four words
Section
The expression - c will also be raised,
So sizeof(-c) is 4 bytes,
But sizeof(c) is one byte

                                                                                            —— By author: Xinxiao · old friend  

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.

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

int main()
{
	int a = 3;
	float f = 5.5;
	float r = a + f;//Arithmetic conversion
	printf("%.1f\n",r);

	return 0;
}

int main()
{
	int a = 10;
	int b = 20;
	a + b;        The expression has two attributes: value attribute and type attribute
	              30 Is the value attribute
	              int Type properties

	return 0;
}

int main()
{
	short s = 20;
	int a = 5;
	printf("%d\n", sizeof(s = a + 4));//?
	printf("%d\n", s);//?

	return 0;
}

 

  If the type of an operand is low in the above list, it must be converted to the type of another operand before performing 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

                                                                                                         —— By author: Xinxiao · old friend  

  12.3 operator properties

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

 

  The calculation path of the same expression has been different! There is a problem with this code! If a.b.c.d.e.f is not only a simple variable, but their respective expressions, the calculation order of these expressions will affect the results!

  Note: in code 1, since * has higher priority than + during calculation, 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;

Note: 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

Code 4
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;
}

static   The function body is not destroyed and accumulation is generated  

  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.

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 in linux, gcc compiler and VS2019. See the results.

  Results of VS2019 environment:

 

Different compilers have different calculation order!

  Look at the same code that produces different results. Why?

Simply look at the assembly code. You can analyze it clearly. When the first + in this code is executed, whether the third + + is executed is uncertain, because depending on the priority and associativity of operators, the order of the first + and the third pre + + cannot be determined.

Summary:

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

                                                                                                                        —— Since   New dawn - old acquaintance

Tags: C

Posted on Tue, 16 Nov 2021 17:47:22 -0500 by theslinky