C语言-基础入门-学习笔记(3):表达式与操作符
1.表达式和语句
语句和表达式可以通过一定的手段来相互转换。
表达式
表达式由操作符和操作数组成。操作符可以由运算操作符、关系操作符和其他操作符组成。操作数是操作符的操作对象,可以是常量或变量。
当为复杂表达式时,需要取决于操作符的优先级,如果想要自己制定优先级,那么可以利用“()”来进行优先级的提前。
运算符表达式优先级的排序如下:
语句
一条完整的语句由表达式和分号组成。表达式可以是最简单的表达式,仅由一个分号组成(空语句)。
复合语句也可以称为程序块,是包含在花括号({})内的多个语句的集合。利用if语句、for语句和while语句构成这些语句的执行体,以实现一些复杂的功能。
2.赋值操作符和表达式
赋值
赋值操作符是一个二元操作符,其组成的赋值表达式的标准形式由变量、赋值操作符和一个表达式组成:
变量 = 表达式;
赋值操作符左边的变量成为左值,右边的表达式成为右值。赋值表达式的值即为语句执行后左值的值。不能使用常量作为左值,因为常量是不可被改编的。
当多个赋值操作符存在于同一条语句中时,将会按照从右到左的结合方式,先执行最右边的赋值操作符,再依次向左执行其余赋值操作符。
类型转换
在赋值表达式中,当把一种类型的数据赋值给不同类型的变量时,编译器会隐式地把该数据进行类型转换,转换为该变量的类型后再赋值。
较少字节的类型向较多字节的类型转换可以,但如果想法会发生数据溢出。
范例1
#include <stdio.h>
int main(void){
long long int large = 0x80000000;
int small = large;
printf("%lld\n",large);
printf("%d\n",small); //数据溢出
return 0;
}
将long long int型量2147483647赋给int型,由于超出了int型变量的范围,会发生数据溢出现象。
范例2
#include <stdio.h>
int main(void){
double pi = 3.1415926;
int i = pi;
printf("%d\n",i);
return 0;
}
当double型量赋给int型,会保留其整数部分,因为Int型不能存储小数部分。
强制类型转换
我们也可以通过强制类型转换的方法来实现类型的转换,由一个圆括号及包含在圆括号里的一个类型名称组成:
(数据类型名) (表达式)
int i = (int) 3.11;
float f = (float) 7;
使用类型转换操作符后,类型转换就会被视为合法的,编译器就不会报错。
范例3
#include <stdio.h>
int main(void){
double pi = 3.1415926;
int i = (int) pi;
double m;
printf("%d\n",i);
m = (int)3.7 + 2.5;
printf("%f\n",m);
m = (int)(3.7 + 2.5);
printf("%f\n",m);
return 0;
}
3.运算操作符和表达式
运算操作符
共有5个,其优先级排序见上面表格,具体的运算规则和方法比较简单,不叙述。
范例4
#include <stdio.h>
int main(void){
int sum = 0;
int average = 0;
int left1 = 0;
int left2 = 0;
sum = 1+2+3+4+5+6+7+8+9+10;
printf("sum = %d\n",sum);//55
sum = (1+10)*10/2;
printf("sum = %d\n",sum);//55
average = sum/10;//5.5但average为int型,所以等于5
left1 = sum % 10;//求余为5
left2 = sum - average * 10;//55-5*10=5
printf("%d = %d * 10 + %d\n",sum,average,left1);
printf("%d = %d - %d * 10\n",left2,sum,average);
return 0;
}
减法操作符的“-”也可以用作符号操作符,表示负数。例如:-2
数值运算中的类型转换
例如:
area = 4 * 7.5
其中4为int型,7.5为double型。int型的4将先被转换为double型,再与double型的7.5相乘。
总结运算规律如下:
- char型和short型数据,不管是unsigned还是signed,在计算中都要先无条件转换为int型,即使是两个char型或short型数值相加。
- float型计算前会无条件转换为double型数值,以增加精度。
- 其余类型的数值计算时,都要转换为数据类型级别较高后在计算。
范例5
#include <stdio.h>
int main(void){
unsigned ui = 0;
int a = 0;
/*如果ui小于1,将a设为1*/
if(0 > (ui-1))
a = 1;
printf("%d\n",a);
printf("%u\n",ui - 1);
return 0;
}
原因为在计算ui - 1时,发生了一个类型转换,ui 为unsigned int型,1为int型,因此,计算时后者转换为unsigned int 型,该表达式值为unsigned int型。当与0比较时,0也转换为无符号型。
复合赋值操作符
左值 += 右值 等效于:左值 = 左值 + 右值
左值 -= 右值 等效于:左值 = 左值 - 右值
左值 *= 右值 等效于:左值 = 左值 * 右值
左值 /= 右值 等效于:左值 = 左值 / 右值
其他情况下也相同
4.自增、自减操作符
后自减操作符的优先级与前自检操作符一样,都比赋值操作符和加法操作符高。自增(或自减)运算符放在操作元之前,先对变量加1(或减1),然后再使用变量的值;自增(或自减)运算符放在操作元之后,先使用变量的值,然后再对变量加1(或减1)。
范例6
#include <stdio.h>
int main(void){
int x = 0;
int y = 0;
x = 2;
y = --x + 1;
printf("y = %d,x = %d\n",y,x);
x = 2;
y = 1 + x--;
printf("y = %d,x = %d\n",y,x);
return 0;
}
编译器的“贪婪法”处理方式:例如++b,假定在编译器解析到第一个加号前,之前所有程序代码都已经正常解析,编译器会尝试向后搜索可以组成某一符号的更长的字符串。
在使用时要尽量将自增表达式和自减表达式作为单独的语句使用。
5.关系操作符和表达式
范例7
//将输入转换为2进制输出
#include <stdio.h>
int main(void){
unsigned a = 0;
do{
printf("Please input a number(0~15):");
scanf("%u",&a);
}while(a > 15);
if(8 <= a){
printf("1");
a -= 8;
}else{
printf("0");
}
if(a >= 4){
printf("1");
a -= 4;
}else{
printf("0");
}
if(1 < a){
printf("1");
a -= 2;
}else{
printf("0");
}
if(a != 1)
printf("0\n");
if(a == 1)
printf("1\n");
return 0;
}
关系表达式的值在C语言中实际上作为int处理。
非0的数值的布尔值为真,而为0的数值的布尔值为假
布尔值为真的关系表达式的int型值为1,布尔值为假的关系式的int型值为0
范例8
#include <stdio.h>
int main(void){
printf("3 > 1 = %d\n",3 > 1);//打印3大于1的值
printf("3 < 1 = %d\n",3 < 1);//打印3小于1的值
printf("sizeof(3 < 1) = %d\n",sizeof(3<1));
return 0;
}
6.逻辑操作符和表达式
逻辑操作符包括与操作符(&&)、或操作符(||)、非操作符(!),其运算结果的值也是BOOL型(为真是等于1,为假时等于0)。
范例9
#include <stdio.h>
int main(void){
printf("1 && 0 == %d\n",1 && 0);
printf("1 && 1 == %d\n",1 && 1);
printf("sizeof(1 && 0) = %d\n",sizeof(1 && 0));
return 0;
}
逻辑非操作符的优先级与符号操作符一致,但高于运算操作符和关系操作符;逻辑与操作符和逻辑或操作符的优先级低于关系操作符,但高于赋值操作符。
7.逗号操作符和表达式
逗号操作符将若干个表达式连接在一起形成一个语句,它的优先级是最低的。
逗号操作符是一个二元操作符,其标准使用形式如下:
表达式1,表达式2;
可以将任意表达式直接作为逗号表达式的子表达式,且不会改变表达式的执行顺序和执行逻辑:
a += 2;
c * 4;
可以转换为:a += 2 , c* 4;
与其他表达式一样,逗号表达式也有一个值,其值是表达式中最后一个子表达式的值,例如:
a = 3;
b = (2,a+3);
则最后结果是:b = 3+3 = 6
注意:不要过于依赖运算符的优先级,应当多实用圆括号来强行设定运算顺序。
练习1
//设计一个程序,输入任一个整数,判断其是否为4、5和6的公倍数
#include <stdio.h>
int main(void){
int ptr = 0;
while(1){
printf("Please enter a number:");
scanf("%d",&ptr);
if((ptr % 4 == 0) && (ptr % 5 == 0) && (ptr % 6 == 0)){
printf("%d is a multiple of 4,5and6.\n",ptr);
}else{
printf("%d is not a multiple of 4,5and6.\n",ptr);
}
return 0;
}
}
练习2
//设计一个多输出的函数
#include <stdio.h>
int main(void){
int x,y = 0;
printf("please enter the number x:");
scanf("%d",&x);
if(x < 1){
y = ++x;
}else if(1<= x && x < 7){
y = 3 * x + 7;
}else{
y = x * x + 3;
}
printf("The result y = %d",y);
return 0;
}