9. Conditional Operators
Composed of question marks and colons, there are three expressions and three operators, so the conditional operator is the only ternary operator, exp1 is true, exp2 is calculated, exp3 is not counted, the result of the entire expression is the result of exp2 . exp1 is false, exp2 is not calculated, exp3 is calculated, and the result of the entire expression is the result of exp3.
exp1 ? exp2 : exp3
The effect of the two codes is the same, which is the usage of the conditional operator.
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int m = 0;
m = (a > b ? a : b);
printf("%d\n", m);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int m = 0;
if (a > b)
m = a;
else
m = b;
printf("%d\n", m);
return 0;
}
10. Comma expressions
exp1, exp2, exp3, …expN
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("c=%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. ( ) 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.
#define _CRT_SECURE_NO_WARNINGS 1
#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;
}
3. Accessing members of a structure
. 结构体.成员名
-> 结构体指针->成员名
This is the usage of the structure member access operator.
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct Book
{
char name[20];
int price;
};
//结构体变量.成员
//结构体指针->成员
void Print(struct Book* pb)
{
printf("%s %d\n", (*pb).name, (*pb).price);
printf("%s %d\n", pb->name, pb->price);
}
int main()
{
struct Book b = {"C语言指南", 55};
printf("%s %d\n", b.name, b.price);
Print(&b);
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 .
Significance of integer promotion :
The integer operation of the expression must be performed 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 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.
The values of a and b are promoted to normal integers before the addition operation is performed.
After the addition is complete, the result is truncated before being stored in c.
How to carry out overall improvement?
Integer promotion is promoted according to the sign bit of the data type of the variable
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//int - signed int
//unsigned int
//char 到底是signed char还是unsigned char是不确定的,C语言标准没有明确指定,是取决于编译器的
//在当前使用的VS上,char == signed char
int main()
{
char a = 5;
//00000000000000000000000000000101
//00000101-存进去的是这8个bit位
char b = 126;
//00000000000000000000000001111110
//01111110
char c = a + b;
//00000000000000000000000000000101-a
//00000000000000000000000001111110-b
//00000000000000000000000010000011
//10000011-c里面只能放这8个bit位
//按照符号位整形提升
//11111111111111111111111110000011
//10000000000000000000000001111100
//10000000000000000000000001111101
//-125
printf("%d\n", c);
return 0;
}
Examples of shaping enhancements:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
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 to be upgraded by plastic, but c does not need to be upgraded by plastic.
After a and b are upgraded by plastic, they become negative numbers, so the result of the expressions a==0xb6 and b==0xb600 is false, but c does not. If plastic promotion occurs, the result of the expression c==0xb6000000 is true.
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 hierarchy below is called ordinary arithmetic conversions .
long double
double
float
unsigned long int
long int
unsigned int
int
If the type of an operand ranks lower in the above list, the operation must first be converted to the type of the other operand.
WARNING:
Arithmetic conversions need to be reasonable though, or there are some potential problems.
float f = 3.14;
int num = f;//隐式转换,会有精度丢失
12.3 Properties of operators
There are three factors that affect the evaluation of complex expressions.
1. The priority of the operator
2. The associativity of the operator
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.
operator precedence
operator _ |
describe | usage example | result type | Combination | whether to control the order of evaluation |
() | group | (expression) | same as expression |
N/A | no |
() | function call | rexp(rexp,...,rexp) | rexp | L-R | no |
[ ] | subscript reference | rexp[rexp] | lexp | L-R | no |
. | access structure members | lexp.member_name | lexp | L-R | no |
-> | access structure pointer member | rexp->member_name | lexp | L-R | no |
++ | suffix increment | lexp ++ | rexp | L-R | no |
-- | suffix decrement | lexp -- | rexp | L-R | no |
! | logical inverse | ! rexp | rexp | R-L | no |
~ | bitwise inversion | ~ rexp | rexp | R-L | no |
+ | Monocular, indicating a positive value | + rexp | rexp | R-L | no |
- | Monocular, representing a negative value | - rexp | rexp | R-L | no |
++ | prefix increment | ++ lexp | rexp | R-L | no |
-- | prefix decrement | -- lexp | rexp | R-L | no |
* | indirect access | * rexp | lexp | R-L | no |
& | take address | & lexp | rexp | R-L | no |
sizeof | Take its length, expressed in bytes |
sizeof rexp sizeof(type ) |
rexp | R-L | no |
( type) |
type conversion | (type) rexp | rexp | R-L | no |
* | multiplication | rexp * rexp | rexp | L-R | no |
/ | division | rexp / rexp | rexp | L-R | no |
% | Integer remainder | rexp % rexp | rexp | L-R | no |
+ | addition | rexp + rexp | rexp | L-R | no |
- | subtraction | rexp - rexp | rexp | L-R | no |
<< | left shift | rexp << rexp | rexp | L-R | no |
>> | right shift | rexp >> rexp | rexp | L-R | no |
> | more than the | rexp > rexp | rexp | L-R | no |
>= | greater or equal to | rexp >= rexp | rexp | L-R | no |
< | less than | rexp < rexp | rexp | L-R | no |
<= | less than or equal to | rexp <= rexp | rexp | L-R | no |
operator _ |
describe | usage example | result type | Combination | whether to control the order of evaluation |
== | equal | rexp == rexp | rexp | L-R | no |
!= | 不等于 | rexp != rexp | rexp | L-R | 否 |
& | 位与 | rexp & rexp | rexp | L-R | 否 |
^ | 位异或 | rexp ^ rexp | rexp | L-R | 否 |
| | 位或 | rexp | rexp | rexp | L-R | 否 |
&& | 逻辑与 | rexp && rexp | rexp | L-R | 是 |
|| | 逻辑或 | rexp || rexp | rexp | L-R | 是 |
? : | 条件操作符 | rexp ? rexp : rexp | rexp | N/A | 是 |
= | 赋值 | lexp = rexp | rexp | R-L | 否 |
+= | 以...加 | lexp += rexp | rexp | R-L | 否 |
-= | 以...减 | lexp -= rexp | rexp | R-L | 否 |
*= | 以...乘 | lexp *= rexp | rexp | R-L | 否 |
/= | 以...除 | lexp /= rexp | rexp | R-L | 否 |
%= | 以...取模 | lexp %= rexp | rexp | R-L | 否 |
<<= | 以...左移 | lexp <<= rexp | rexp | R-L | 否 |
>>= | 以...右移 | lexp >>= rexp | rexp | R-L | 否 |
&= | 以...与 | lexp &= rexp | rexp | R-L | 否 |
^= | 以...异或 | lexp ^= rexp | rexp | R-L | 否 |
|= | 以...或 | lexp |= rexp | rexp | R-L | 否 |
, | 逗号 | rexp,rexp | rexp | L-R | 是 |
我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题
的。
今天的分享到这里就结束啦!谢谢老铁们的阅读,让我们下期再见。