[嵌入式C][入门篇] 快速掌握基础3 (运算符)

发布时间:2024年01月07日

开发环境:

  1. 网页版:跳转
  2. 本地开发(Vscode):跳转

一、 简介

运算符类型作用
算术运算符用于处理四则运算
赋值运算符用于将表达式的值赋给变量
比较运算符用于表达式的比较,并返回一个真值或假值
逻辑运算符用于根据表达式的值返回真值或假值
位运算符用于处理数据的位运算
sizeof运算符用于求字节数长度(编译器预处理,不影响运行效率)

二、算术运算符

运算符描述实例
+把两个操作数相加A + B 将得到 30
-从第一个操作数中减去第二个操作数A - B 将得到 -10
*把两个操作数相乘A * B 将得到 200
/分子除以分母B / A 将得到 2
%取模(取余)运算符,整除后的余数B % A 将得到 0
++自增运算符,整数值增加 1A++ 将得到 11
自减运算符,整数值减少 1A-- 将得到 9

(1)示例代码:

#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);
}

在这里插入图片描述

(2)++和–的先后顺序(直接看效果)

在这里插入图片描述

#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为假。

(1)示例代码

#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为10 & 0 = 0;
0 & 1 = 0;
1 & 0 = 0;
1 & 1 = 1;
|位或有1为1 ,全0位00 | 0 = 0;
0 | 1 = 1;
1 | 0 = 1;
1 | 1 = 1;
^位异或相同为0,不同为10 ^ 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

(1) 真值表

位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:

pqp & q (与)p | q(或)p ^ q(异或)
00000
01011
11110
10011

(2) 示例代码

#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

(1) 示例代码

#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) 为真。

(1) 示例代码

#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

(1) 示例代码

#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逗号,从左到右
文章来源:https://blog.csdn.net/qq_29246181/article/details/135388002
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。