和数学中的运算符一样, C语言中的运算符是告诉程序执行特定算术或逻辑操作的符号
什么是表达式: 表达式就是利用运算符链接在一起的有意义,有结果的语句; 例如: a + b; 就是一个算数表达式, 它的意义是将两个数相加, 两个数相加的结果就是表达式的结果 注意: 表达式一定要有结果
按照功能划分:
按照参与运算的操作数个数划分:
早在小学的数学课本中,我们就学习过"从左往右,先乘除后加减,有括号的先算括号里面的", 这句话就蕴含了优先级和结合性的问题
C语言中,运算符的运算优先级共分为15 级。1 级最高,15 级最低
注意事项
在程序设计中,经常遇到“i=i+1”和“i=i-1”这两种极为常用的操作。C语言为这种操作提供了两个更为简洁的运算符,即++
和--
如果出现在一个表达式中, 那么符号写在前面和后面就会有所区别
++x, --x;
其中x表示变量名,先完成变量的自增自减1运算,再用x的值作为表达式的x++, x--;
先用x的当前值作为表达式的值,再进行自增自减1运算。即“先用后变”,也自增:
如果只有单个变量, 无论++写在前面还是后面都会对变量做+1操作
如果自增参与运算
自减
注意:
++(a+b);
++ --
单独出现, 尽量不要和其它运算符混合在一起请用如下代码替代
C语言标准没有明确的规定, 同一个表达式中同一个变量自增或自减后如何运算 , 不同编译器得到结果也不同, 在企业开发中千万不要这样写
sizeof可以用来计算一个变量或常量、数据类型所占的内存字节数
标准格式: sizeof(常量 or 变量);
sizeof()和+=、*=
一样是一个复合运算符, 由sizeof和()两个部分组成, 但是代表的是一个整体
所以sizeof不是一个函数, 是一个运算符, 该运算符的优先级是2
sizeof的几种形式:
// sizeof( 变量\常量 );
sizeof(10);
char c = 'a';
sizeof(c);
//sizeof 变量\常量;
sizeof 10;
char c = 'a';
sizeof c;
// sizeof( 数据类型);
sizeof(float); //如果是数据类型不能省略括号
表达式1,表达式2,… …,表达式n;
#include <stdio.h>
int main(){
int a=2,b=4,x,y;
y=(x=a+b,b+x); //在逗号表达式中,最后一个运算才是最终的值,然后赋值给y
printf("y=%d, x=%d \n",y,x);// y=10, x=6
return 0;
}
默认情况下,我们在程序中写的每一句正确代码都会被执行。但很多时候,我们想在某个条件成立的情况下才执行某一段代码, 这种情况的话可以使用条件语句来完成,但是学习条件语句之前,我们先来看一些更基础的知识:
如何判断一个条件是否成立, C语言中的真假性 , 在C语言中,条件成立称为“真”,条件不成立称为“假”,因此,判断条件是否成立,就是判断条件的“真假”
怎么判断真假呢?C语言规定,任何数值都有真假性,任何非0值都为“真”,只有0才为“假”。也就是说,108、-18、4.5、-10.5等都是“真”
,0则是“假
关系运算符的运算结果只有2种:如果条件成立,结果就为1,也就是“真”;
如果条件不成立,结果 就为0,也就是“假
优先级和结合性
注意: 无论是float还是double都有精度问题, 所以一定要避免利用==判断浮点数是否相等
优先级 | 名称 | 符号 | 说明 |
---|---|---|---|
2 | 逻辑非运算符 | ! | 单目运算符,具有右结合性 |
11 | 逻辑与运算符 | && | 双目运算符,具有左结合性 |
12 | 逻辑或运算符 | || | 双目运算符,具有左结合性 |
格式: ! 条件A; (真变假,假变真)
格式: 条件A && 条件B;
运算结果:一假则假 ,也就是都为真那么才是真
**运算过程:**
使用注意: 条件A"为假, "条件B"不会被执行
格式: 条件A || 条件B;
运算结果:一真则真
**运算过程:**
使用注意: "条件A"为真, "条件B"不会被执行
三目运算符,它需要3个数据或表达式构成条件表达式
格式1: 表达式1?(结果A):(结果B)
格式2: 表达式1?表达式2:表达式3
示例: 考试及格 ? 及格 : 不及格;
求值规则: 如果"表达式1"为真,三目运算符的运算结果为(结果A),否则为(结果B)
我们还可以进行复杂点的 int res = a>b?a:(c>d?c:d);
数据类型转换就是将数据(变量、数值、表达式的结果等)从一种类型转换为另一种类型。
自动类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生。将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换,例如:
//100 是 int 类型的数据,需要先转换为 float 类型才能赋值给变量 f。
float f = 100;
//再如:f 是 float 类型的数据,需要先转换为 int 类型才能赋值给变量 n。
int n = f;
在赋值运算中,赋值号两边的数据类型不同时,需要把右边表达式的类型转换为左边变量的类型,这可能会导致数据失真,或者精度降低;所以说,自动类型转换并不一定是安全的。对于不安全的类型转换,编译器一般会给出警告。
在不同类型的混合运算中,编译器也会自动地转换数据类型,将参与运算的所有数据先转换为同一种类型,然后再进行计算。转换的规则如下:
下图对这种转换规则进行了更加形象地描述:
unsigned 也即 unsigned int,此时可以省略 int,只写 unsigned。
自动类型转换示例:
#include<stdio.h>
int main(){
float PI = 3.14159;
int s1, r = 5;
double s2;
s1 = r * r * PI;
s2 = r * r * PI;
printf("s1=%d, s2=%f\n", s1, s2);
return 0;
}
在计算表达式r*r*PI
时,r 和 PI 都被转换成 double 类型,表达式的结果也是 double 类型。但由于 s1 为整型,所以赋值运算的结果仍为整型,舍去了小数部分,导致数据失真。
自动类型转换是编译器根据代码的上下文环境自行判断的结果,有时候并不是那么“智能”,不能满足所有的需求。如果需要,程序员也可以自己在代码中明确地提出要进行类型转换,这称为强制类型转换。
自动类型转换是编译器默默地、隐式地进行的一种类型转换,不需要在代码中体现出来;强制类型转换是程序员明确提出的、需要通过特定格式的代码来指明的一种类型转换。换句话说,自动类型转换不需要程序员干预,强制类型转换必须有程序员干预。
强制类型转换的格式为:(type_name) expression
type_name为新类型名称,expression为表达式。例如:
(float) a; //将变量 a 转换为 float 类型
(int)(x+y); //把表达式 x+y 的结果转换为 int 整型
(float) 100; //将数值 100(默认为int类型)转换为 float 类型
下面是一个需要强制类型转换的经典例子:
#include <stdio.h>
int main(){
int sum = 103; //总数
int count = 7; //数目
double average; //平均数
average = (double) sum / count;
printf("Average is %lf!\n", average); //Average is 14.714286!
return 0;
}
sum 和 count 都是 int 类型,如果不进行干预,那么sum / count的运算结果也是 int 类型,小数部分将被丢弃;虽然是 average 是 double 类型,可以接收小数部分,但是心有余力不足,小数部分提前就被“阉割”了,它只能接收到整数部分,这就导致除法运算的结果严重失真。
既然 average 是 double 类型,为何不充分利用,尽量提高运算结果的精度呢?为了达到这个目标,我们只要将 sum 或者 count 其中之一转换为 double 类型即可。上面的代码中,我们将 sum 强制转换为 double 类型,这样sum / count的结果也将变成 double 类型,就可以保留小数部分了,average 接收到的值也会更加精确。
在这段代码中,有两点需要注意:
无论是自动类型转换还是强制类型转换,都只是为了本次运算而进行的临时性转换,转换的结果也会保存到临时的内存空间,不会改变数据本来的类型或者值。请看下面的例子:
#include <stdio.h>
int main() {
double total = 400.8; //总价
int count = 5; //数目
double unit; //单价
int total_int = (int)total; //400
unit = total / count; // 80.160000
printf("total=%lf, total_int=%d, unit=%lf\n", total, total_int, unit); //total=400.800000, total_int=400, unit=80.160000
return 0;
}
通过上面的代码,我们能看出来,total虽然转换了类型给了total_int ,但是total 原本的数据类型没有发生变化,所以最后计算的时候还是小数 ,也就表明类型转换只是占时的只是作用在当前的计算
在C语言中,有些类型既可以自动转换,也可以强制转换,例如 int 到 double,float 到 int 等;而有些类型只能强制转换,不能自动转换,例如以后将要学到的 void * 到 int *,int 到 char * 等。
可以自动转换的类型一定能够强制转换,但是,需要强制转换的类型不一定能够自动转换。现在我们学到的数据类型,既可以自动转换,又可以强制转换,以后我们还会学到一些只能强制转换而不能自动转换的类型。
可以自动进行的类型转换一般风险较低,不会对程序带来严重的后果,例如,int 到 double 没有什么缺点,float 到 int 顶多是数值失真。只能强制进行的类型转换一般风险较高,或者行为匪夷所思,例如,char * 到 int * 就是很奇怪的一种转换,这会导致取得的值也很奇怪,再如,int 到 char * 就是风险极高的一种转换,一般会导致程序崩溃。 使用强制类型转换时,程序员自己要意识到潜在的风险。
点赞 -收藏-关注-便于以后复习和收到最新内容有其他问题在评论区讨论-或者私信我-收到会在第一时间回复感谢,配合,希望我的努力对你有帮助^_^
免责声明:本文部分素材来源于网络,版权归原创者所有,如存在文章/图片/音视频等使用不当的情况,请随时私信联系我。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://huanmin.blog.csdn.net/article/details/125586562
内容来源于网络,如有侵权,请联系作者删除!