开发环境:
运算符类型 | 作用 |
---|---|
算术运算符 | 用于处理四则运算 |
赋值运算符 | 用于将表达式的值赋给变量 |
比较运算符 | 用于表达式的比较,并返回一个真值或假值 |
逻辑运算符 | 用于根据表达式的值返回真值或假值 |
位运算符 | 用于处理数据的位运算 |
sizeof运算符 | 用于求字节数长度(编译器预处理,不影响运行效率) |
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模(取余)运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
– | 自减运算符,整数值减少 1 | A-- 将得到 9 |
#include <stdio.h>
int main() {
int a = 21;
int b = 10;
int c ;
printf("a + b = %d\n", a + b);
printf("a - b = %d\n", a - b);
printf("a * b = %d\n", a * b);
printf("a / b = %d\n", a / b);
printf("a % b = %d\n\n", a % b);
c = a++; // a赋值后再加 1 ,c 为 21,a 为 22
printf("c = %d, a = %d\n", c, a);
c = a--; // a赋值后再减 1 ,c 为 22 ,a 为 21
printf("c = %d, a = %d\n", c, a);
}
#include <stdio.h>
int main(){
int c;
int a = 10;
c = a++;
printf("先赋值后运算:c=%d, a=%d\n", c, a); // a赋值后再加1,c 为 10,a 为 11
a = 10;
c = a--;
printf("先赋值后运算:c=%d, a=%d\n", c, a); // a赋值后再减1,c 为 10 ,a 为 9
a = 10;
c = ++a;
printf("先运算后赋值:c=%d, a=%d\n", c, a); // a加1后再赋值,c 为 11,a 为 11
a = 10;
c = --a;
printf("先运算后赋值:c=%d, a=%d\n", c, a); // a加1后再赋值,c 为 9,a 为 9
}
C 语言的比较运算中, “真”用数字“1”来表示, “假”用数字“0”来表示
运算符 | 术语 | 描述 | 实例 |
---|---|---|---|
&& | 与 | a && b | 如果a和b都为真,则结果为真,否则为假。 |
|| | 或 | a || b | 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。 |
! | 非 | !a | 如果a为假,则!a为真; 如果a为真,则!a为假。 |
#include <stdio.h>
#include <stdbool.h>
// true = 1 = 真
// false = 0 = 假
int main() {
bool a = true;
bool b = true;
bool c = false;
bool d = false;
printf("---[与]需要条件同时满足才能为真---\n\n");
printf("a && b = %d\n" , a && b); // 真 && 真 = 真
printf("a && c = %d\n" , a && c); // 真 && 假 = 假
printf("c && d = %d\n\n" , c && d); // 假 && 假 = 假
printf("---[或]只有任意一个条件满足即可---\n\n");
printf("a || b = %d\n" , a || b); // 真 || 真 = 真
printf("a || c = %d\n" , a || c); // 真 || 假 = 真
printf("c || d = %d\n\n" , c || d); // 假 || 假 = 假
printf("---[非] 取反---\n\n");
printf("!(a && b) = %d\n" , !(a && b)); // !(真 && 真 = 真) = 假
printf("!(a && c) = %d\n" , !(a && c)); // !(真 && 假 = 假) = 真
}
运算符 | 术语 | 描述 | 实例 |
---|---|---|---|
& | 位与 | 有0为0,全1为1 | 0 & 0 = 0; 0 & 1 = 0; 1 & 0 = 0; 1 & 1 = 1; |
| | 位或 | 有1为1 ,全0位0 | 0 | 0 = 0; 0 | 1 = 1; 1 | 0 = 1; 1 | 1 = 1; |
^ | 位异或 | 相同为0,不同为1 | 0 ^ 0 = 0; 0 ^ 1 = 1; 1 ^ 0 = 1; 1 ^ 1 = 0; |
~ | 位取反 | 0变1,1变0 | ~1 = -2; ~0 = -1; |
<< | 左移 | 左移 n 位相当于乘以 2 的 n 次方。 | A << 2 将得到 240,即为 1111 0000 |
>> | 右移 | 右移n位相当于除以 2 的 n 次方 | A >> 2 将得到 15,即为 0000 1111 |
位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
p | q | p & q (与) | p | q(或) | p ^ q(异或) |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
#include <stdio.h>
#include <stdint.h>
#include <string.h>
char *itoa(uint32_t value, char *string, uint8_t radix);
int main() {
uint8_t a = 60; /* 60 = 0011 1100 */
uint8_t b = 13; /* 13 = 0000 1101 */
uint8_t c = 0;
char a_B[10]={0}; // 存放A值的二进制
char b_B[10]={0}; // 存放B值的二进制
char val_B[10]={0}; // 结果的二进制
itoa(a&b, val_B, 2); // 10进制转2进制
itoa(a, a_B, 2); // 10进制转2进制
itoa(b, b_B, 2); // 10进制转2进制
printf("[位与] 如果两个相应的位都为 1,则结果为 1,否则为 0。\r\n");
printf("[位与] a & b = %d, 计算过程:\r\n", a & b); // 0000 1100 = 12
printf("\t二进制:a = %s\n\t二进制:b = %s\n\t\t val = %s\n", a_B, b_B, val_B);
printf("--------------------------------------------\n\n");
itoa(a|b, val_B, 2); // 10进制转2进制
itoa(a, a_B, 2); // 10进制转2进制
itoa(b, b_B, 2); // 10进制转2进制
printf("[位或] 如果两个相应的位都为 0,则结果为 0,否则为 1。\r\n");
printf("[位或] a | b = %d, 计算过程:\r\n", a | b); // 0011 1101 = 61
printf("\t二进制:a = %s\n\t二进制:b = %s\n\t\t val = %s\n", a_B, b_B, val_B);
printf("--------------------------------------------\n\n");
itoa(a^b, val_B, 2); // 10进制转2进制
itoa(a, a_B, 2); // 10进制转2进制
itoa(b, b_B, 2); // 10进制转2进制
printf("[位异或] 如果两个相应的位值相同,则结果为 0,否则为 1。\r\n");
printf("[位异或] a ^ b = %d, 计算过程:\r\n", a ^ b); // 0011 0001 = 49
printf("\t二进制:a = %s\n\t二进制:b = %s\n\t\t val = %s\n", a_B, b_B, val_B);
printf("--------------------------------------------\n\n");
itoa(a, a_B, 2); // 10进制转2进制
itoa((uint8_t)(~a), val_B, 2); // 10进制转2进制
printf("[取反] 将每一位的 0 变为 1,1 变为 0。\r\n");
printf("[取反] ~a = %d, 计算过程:\r\n", ~a); // 1100 0011 = -61
printf("\t二进制:a = %s\n\t\t val = %s\n", a_B, val_B);
printf("--------------------------------------------\n\n");
itoa(a, a_B, 2); // 10进制转2进制
itoa((uint8_t)(a << 2), val_B, 2); // 10进制转2进制
printf("[左移] 左移 n 位相当于乘以 2 的 n 次方。\r\n");
printf("[左移] a<<2 = %d, 计算过程:\r\n", a << 2); // 1111 0000 = 240
printf("\t二进制:a = %s\n\t\t val = %s\n", a_B, val_B);
printf("--------------------------------------------\n\n");
itoa(a, a_B, 2); // 10进制转2进制
itoa((uint8_t)(a >> 2), val_B, 2); // 10进制转2进制
printf("[右移] 右移n位相当于除以 2 的 n 次方。\r\n");
printf("[右移] a>>2 = %d, 计算过程:\r\n", a >> 2); // 00001111 = 15
printf("\t二进制:a = %s\n\t\t val = %s\n", a_B, val_B);
printf("--------------------------------------------\n\n");
}
// value 被转换的整数,*string 转换后储存的字符数组radix 转换进制数,如2,8,10,16 进制等。
char *itoa(uint32_t value,char *string,uint8_t radix) {
char zm[37]="0123456789abcdefghijklmnopqrstuvwxyz";
char aa[100]={0};
int sum=value;
char *cp=string;
int i=0;
if(radix < 2||radix > 36){ //增加了对错误的检测
printf("error data!\r\n");
return string;
}
if(value<0){
printf("error data!\r\n");
return string;
}
while(sum>0){
aa[i++]=zm[sum%radix];
sum/=radix;
}
for(int j=i-1;j>=0;j--){
*cp++=aa[j];
}
*cp='\0';
cp=string;
//printf("%d|%s|%d\r\n", i, string,value);
if (i < 8) {
memmove(cp + (8-i), cp, i);
for(int j=0;j<8-i;j++){
*cp++='0';
}
} else if (i < 16 && i >8) {
memmove(cp + (8-i), cp, i);
for(int j=0;j<16-i;j++){
*cp++='0';
}
} else if (i < 32 && i >16) {
memmove(cp + (8-i), cp, i);
for(int j=0;j<32-i;j++){
*cp++='0';
}
}
//printf("%d|%s|%d\r\n", i, string,value);
return string;
}
运算符 | 描述 | 实例 |
---|---|---|
= | 等号,数学概念 | C = A + B 将把 A + B 的值赋给 C |
+= | 加某个值,缩写的形式 | C += A 相当于 C = C + A |
-= | 减某个值,缩写的形式 | C -= A 相当于 C = C - A |
*= | 乘某个值,缩写的形式 | C *= A 相当于 C = C * A |
/= | 除个值,缩写的形式 | C /= A 相当于 C = C / A |
%= | 求余某个值,缩写的形式 | C %= A 相当于 |
<<= | 左移某个值,缩写的形式 | C <<= 2 等同于 C = C << 2 |
>>= | 右移某个值,缩写的形式 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与某个值,缩写的形式 | C &= 2 等同于 C = C & 2 |
^= | 按位异或某个值,缩写的形式 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或某个值,缩写的形式 | C |= 2 等同于 C = C |
#include <stdio.h>
int main() {
int a = 4;
int c = 0;
printf("a = %d\r\n", a);
c = a;
printf("[等号] c = a ,结果:c = %d\n", c);
a += 2;
printf("[相加] a += 2,等价:a = a + 2, 结果: %d\n", a);
a = 4;
a -= 2;
printf("[相减] a -= 2,等价:a = a - 2, 结果:%d\n", a);
a = 4;
a *= 2;
printf("[相乘] a *= 2,等价:a = a * 2, 结果:%d\n", a);
a = 4;
a /= 2;
printf("[相除] a /= 2,等价:a = a ÷ 2, 结果:%d\n", a);
a = 4;
a %= 2;
printf("[求余] a %= 2,等价:a = a %% 2, 结果:%d\n", a);
a = 4;
a <<= 2;
printf("[左移] a <<= 2,等价:a = a << 2, 结果:%d\n", a);
a = 4;
a >>= 2;
printf("[右移] a >>= 2,等价:a = a >> 2, 结果:%d\n", a);
a = 4; // 4 = 100
a &= 3; // 3 = 011 如果两个相应的位都为 1,则结果为 1,否则为 0。
printf("[位与] a &= 3,等价:a = a & 3, 结果:%d\n", a);
a = 4; // 4 = 100
a |= 2; // 2 = 010 如果两个相应的位都为 0,则结果为 0,否则为 1。
printf("[位或] a |= 2,等价:a = a | 2, 结果:%d\n", a);
a = 4; // 4 = 100
a ^= 2; // 2 = 010 如果两个相应的位值相同,则结果为 0,否则为 1。
printf("[位异或] a ^= 2,等价:a = a ^ 2, 结果:%d\n", a);
}
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 为假。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B) 为假。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 为假。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
#include <stdio.h>
int main() {
int a = 21;
int b = 10;
printf("a=%d, b=%d. 结果:1--成立 0--不成立\n", a, b);
printf("a == b, 结果:%d\n", a == b);
printf("a < b, 结果:%d\n", a < b);
printf("a > b, 结果:%d\n", a > b);
printf("a >= b, 结果:%d\n", a >= b);
printf("a <= b, 结果:%d\n", a <= b);
}
运算符 | 描述 | 实例 |
---|---|---|
sizeof() | 返回变量的大小。 | sizeof(a) 将返回 4,其中 a 是整数。 |
& | 返回变量的地址。 | &a; 将给出变量的实际地址。 |
* | 指向一个变量。 | *a; 将指向一个变量。 |
? : | 三目表达式 | 如果条件为真 ? 则值为 X : 否则值为 Y |
[ ] | 下标运算符,数组的时候使用的 | a[10], b[20] |
. | 引用运算符,结构体的时候使用 | a.cnt, b.size |
-> | 指向运算符,结构体指针的时候使用 | a->cnt, b->size |
#include <stdio.h>
#include <stdint.h>
typedef struct { // 字节对齐,按最大成员字节转换
uint8_t cnt; // 编译器强制转换为uint16_t
uint16_t size;
} xjq_t;
int main() {
xjq_t lisun = {1, 4};
uint8_t a[10], b[20];
printf("取变量大小: sizeof(xjq_t), 结果:%d\n\n", sizeof(xjq_t));
printf("取变量地址:&lisun, 结果:0x%X\n\n", &lisun);
printf("三目运算:(lisun.cnt == 0) ? 1 : 0, 结果:%d\n\n", (lisun.cnt == 0) ? 1 : 0);
a[0] = 0; a[1] = 1; a[2] = 2;
printf("数组下标: a[1], 结果:%d\n\n", a[1]);
printf("引用运算符: lisun.cnt lisun.size, 结果:%d, %d\n\n", lisun.cnt, lisun.size);
xjq_t *p = &lisun; // 将地址传递给指针
printf("指向运算符: p->cnt p->size, 结果:%d, %d\n\n", p->cnt, p->size);
}
优先级 | 类别 | 运算符 | 平级时 |
---|---|---|---|
1 | 后缀 | () [] -> . ++ - - | 从左到右 |
2 | 一元 | + - ! ~ ++ - - (type)* & sizeof | 从右到左 |
3 | 乘除 | * / % | 从左到右 |
4 | 加减 | + - | 从左到右 |
5 | 移位 | << >> | 从左到右 |
6 | 关系 | < <= > >= | 从左到右 |
7 | 相等 | == != | 从左到右 |
8 | 位与 | & | 从左到右 |
9 | 位异或 | ^ | 从左到右 |
10 | 位或 | | | 从左到右 |
11 | 与 | && | 从左到右 |
12 | 逻辑或 OR | || | 从左到右 |
13 | 三目运算符 | ?: | 从右到左 |
14 | 赋值 | = += -= *= /= %=>>= <<= &= ^= |= | 从右到左 |
15 | 逗号 | , | 从左到右 |