5.C基础_运算符

 运算符概述

相关名词

对于" a=b+c "

  • 这个式子被称为表达式
  • " = "和" + "被称为运算符
  • 参与运算的b、c被称为操作数
  • " + "操作数的个数为2,所以" + "的运算符分类为双目运算符

优先级

1、除法运算符 " / "

除号的两端都是整数时,结果也为整数。

int a = 7/2;// 7/2=3.5,取整数为3,不进行四舍五入

除号的两端有浮点数时,结果为浮点数(自动类型转换)

int a = 7/2.0;// 7/2=3.5 2.0为double型,因此结果也为double型,保留小数

2、取余运算符 " % "

取余运算符的两个操作数只能为整数

下面为取余运算的应用:

2.1 实现多位数的分离

有一个不知多少位的数(比如说123),现在要将其各个位进行分离存入到一个数组中,要求低位存入低地址(比如1存入buf[2]、2存入buf[1],3存入buf[0])。

代码实现如下:

#include <stdio.h>
#include <math.h>
#include <stdlib.h> 

/* 拆分一个整数,将各个位存入数组,第0位存入个位 */
/* 返回值:动态创建的数组首地址,失败返回NULL */
char* Split_Num(int num){
	
	char* Split_Num_point = NULL;
	char* point_tmp = NULL;
	int digit = 1;//传入num的位数
	int i=0;//循环控制变量 
	int num_tmp = num;
	
	/* 1.遍历,直到个位 */
	while(1){
		
		num_tmp/=10;
		if(num_tmp == 0){ //num/10=0代表已经到达了个位  
			break;
		}
		digit++;
	}
	printf("Debug:digit = %d\n",digit);
	
	/* 2.开辟数组空间 */
	//有多少位就开辟多少空间+1,多的1个空间是用来存'\0' 
	Split_Num_point = (char*)malloc(sizeof(char)*(digit+1));
	point_tmp = Split_Num_point; 
	if(Split_Num_point == NULL){
		printf("malloc err\n");
		return NULL;
	}
	printf("Debug:malloc success\n");
	
	/* 3.从最高位开始,获取每一位的值 */
	num_tmp = num;
	printf("Debug:num_tmp = %d\n",num_tmp);  
	point_tmp += digit;//指针偏移到数组末尾
	*point_tmp = '\0';
	point_tmp--;
	for(i=digit-1;i>0;i--){
		*point_tmp = num_tmp/pow(10,i);
		num_tmp = num_tmp%((int)pow(10,i));
		
		printf("Debug:i=%d,*point_tmp = %d\n",i,*point_tmp);
		printf("Debug:i=%d,num_tmp = %d\n",i,num_tmp);  
		point_tmp--;
	}
	*point_tmp = num_tmp;
	printf("Debug:i=%d,*point_tmp = %d\n",i,*point_tmp);
	
	return Split_Num_point;
}

void print_str(char* str){
	
	char* point = str;
	
	while(*point != '\0'){
		printf("%d",*point);
		point++;
	}
}

int main(){
	
	char* p;
	
	p = Split_Num(87123);
	print_str(p);
	
	return 0;
}

代码使用方法:

将一个int类型的数据传入函数Split_Num,最终返回一个char*的动态开辟的数组首地址。数组的最低位为传入数据的最低位,在上述代码中,传入87123,那么*p就是3。

3、自增自减运算符

"++"、" -- "可以放在变量前(前置),也可以放在变量后(后置)

前置:例如++val,代表先对val进行加1,再进行赋值

后置:例如val++,代表先进行赋值,再对val进行加1

int val_1=0;
int val_2=0;

printf("val_1++ = %d,val_1 = %d\n",val_1++,val_1);//先用再加,打印 0,最终val = 1 
printf("++val_2 = %d,val_2 = %d\n",++val_2,val_2);//先加再用,打印 1,最终val = 1 

4、位运算符

4.1 按位取反(~):

按位取反(~)只能用作于整型数据," ~ "的优先级很高,只比" () "低一级 

对于有符号数和无符号数,取反都是一样的,最高位都会从0->1或1->0。

按位取反时需要考虑变量类型的存储内存大小,具体示例如下:

unsigned int a = 0x20; //0010 0000
a = a >> 2;            //0000 1000
a = ~a;                //1111 0111
printf("%x",a);        //因为int为4字节,所以会再前面补0,取反后会全部变成1
//最终结果为0xfffffff7	

4.2 按位异或(^):

按位异或(^)具有0与某个数异或等于它本身的性质,即:0^n=n

按位异或实现原地交换:

#include <stdio.h>

int main(){
	
	int a=0x78;
	int b=0x12;	
	a=a^b;  
	b=a^b;//b=0x78
	a=a^b;//a=0x12
	printf("a=%x,b=%x\n",a,b);	
	/* 运算过程解释 */	
	/*
	a=原a^原b
	
	b=a^原b
	 =(原a^原b)^原b
	 =原a^(原b^原b)
	 =原a^0
	 =原a
	
	a=a^b
	 =原a^原b^b
	 =原a^原b^原a
	 =(原a^原a)^原b
	 =0^原b
	 =原b	
	*/
	return 0;
} 

4.3 移位(<<  >>):

移位(<<  >>)只能用作于整型数据。

对于无符号数,移位后的空位补0。

  • 左移就相当于*2^n,比如0000 0001<<2,就时0x01*2^2 = 4,即:0000 0100
  • 右移就相当于/2^n,比如0000 0100>>2,就时0x04/2^2 = 1,即:0000 0001 

对于有符号数,右移位后符号位正数补0,负数补1(左移不补),其余操作与无符号数一致。

  • 左移(负数):比如1000 0001<<1,这是个负数,所以最高位不补,结果为0000 0010
  • 左移(正数):比如0000 0001<<1,这是个正数,所以最高位不补,结果为0000 0010
  • 右移(负数):比如1000 0001>>1,这是个负数,所以最高位补1,结果为1100 0000
  • 右移(正数):比如0000 0001>>1,这是个正数,所以最高位补0,结果为0000 0000

4.4 按位与、按位或( &  | )

任意数 & 0 = 0,因此按位与(&)常常用作对某一位进行清零

任意数 | 1 = 1,因此按位或( | )常常用作对某一位进行置1

任意数 ^ 1 = 取反,因此按位异或(^)常常用作对某一位进行取反

  • 清0第n位:a &= ~(1<<n)
  • 置1第n位:a |= (1<<n)
  • 取反第n位:a ^= (1<<n)

5、关系运算符

关系运算符就是>、<、==、!=这些。在使用关系运算符时,应该将常量放在左边,变量放在右边,以减少" == "写为" = "时查不出bug的情况

例如应该写为 if(-1==val),而不是 if(val == -1)

6、逻辑运算符

逻辑运算符就是&&、||、! 这些。其中&&、||具有短路特性,即:表达式从左往右执行,若左边已经能决定表达式结果,则后面不再执行。

  • &&短路特性:左边为0时,右边不再执行
  • ||短路特性:左边为1时,右边不再执行

验证例程如下:

int a = 0, b = -1, c = 3, d = 4;
c = a++ && ++ b && d++;
printf(“a = %d\n b = %d\n c = %d\n d = %d\n”, a, b, c, d);

因为a++为先用再加,所以是a=0进行&&运算。0已经能决定&&运算,因此++b、d++都不再运行。最终结果为a=1、b=-1、c=0、d=4

编程规范:

因为短路特性的存在,在编程中应该将最可能为1的表达式放在||左边,最可能为0的表达式放在&&左边,以达到最大程度的使用短路特性,提高代码执行效率。

7、条件运算符

条件运算符的形式为:<条件>?<表达式1>:<表达式2>

  • 若条件为1,值为表达式1的值
  • 若条件为0,值为表达式2的值

验证例程如下:

int x,y=25;
x=70;
y= x++ > 70 ? 100 : 20 ;
printf("x=%d y=%d",x,y); 

因为x++为先用再加,所以是x=70进行>70的判断,结果为假,y被赋值为20。因为x++,所以x值为71。

8、逗号运算符

逗号运算符从左向右执行各个表达式,值为最后一个表达式的值。

验证例程如下:

int x,y,z;
z=(x=y=5,x++);
printf("x=%d,y=%d,z=%d",x,y,z);	

首先运行x=y=5,这是x=5、y=5;再运行x++,因为x++为先用再加,所以表达式值为5而不是6,因此z被赋值为5。最终结果为x=6、y=5、z=5。

  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值