catalogue
—— By author: Xinxiao · old friend
six point one sizeof and arrays
1.test (test in the main function) passes the address of the first element!
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.3. Access to members of a structure
Significance of integer lifting:
Integer promotion is promoted according to the sign bit of the data type of the variable
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