(七)关系操作符
< <= > >= != ==
都挺简单,唯一注意=和==
(八)逻辑操作符
逻辑与 &&
逻辑或 ||
#include<stdio.h>
int main()
{
int a = 9;
int b = 1;
int c = 0;
printf("%d\n", a & b);
printf("%d\n", a | b);//更多的是计算
printf("%d\n", a && b);
printf("%d\n", a || b);//更多的是逻辑判断
return 0;
}
在c语言中,非0为真,0为假;
笔试题分析:
#include <stdio.h>
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++ && ++b && d++;
printf(" a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d);
return 0;
}
&&的特点是只要前面运算为假了,后面的运算全部不进行。(因为都为假)
所以当计算到a++时,先使用a=0为假,后面运算停止,而a++使a自增1。
同理,当||遇到真时,后面的运算取消:
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
//i = a++ && ++b && d++;
i = a++||++b||d++;
printf(" a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d);
return 0;
}
(九)条件操作符---三目操作符
exp1?exp2:exp3
含义:
若1结果为真,计算表达式2,其结果为整个表达式的结果
若1结果为假,计算表达式3,其结果为整个表达式的结果
练习:
#include<stdio.h>
int main()
{
int a = 20;
int b = 10;
b = (a > b ? a : b);
printf("%d", b);
return 0;
}
(十)逗号表达式
exp1,exp2,exp3........expn
就是用逗号把多个式子隔开,从左向右依次执行,整个表达式的结果就是最后一个表达式的结果。
1.
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
a=12;b=13;c=13
2.
if (a =b + 1, c=a / 2, d > 0)
取决于d>0;
(十一)下标引用,函数调用和结构成员
1.【】下标引用操作符
操作数:一个数组名+一个索引值
int arr[10];
arr[9]=10;
2.()函数调用操作符
接受一个或多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
int max=get_max(a,b) //3个操作数
3.访问一个结构的成员
结构体.成员名
结构体指针->成员名
#include<stdio.h>
struct Stu //创建了一个结构体类型————struct Stu
{
char name[20];
int age;
char id[20];
};
int main()
{
int a = 10;
struct Stu s1 = { "小明",20,"10293845648" }; //使用struct Stu创建了一个学生对象s1
struct Stu* ps = &s1;
printf("%s\n", ps->name);
printf("%d\n", ps->age);
//printf("%s\n", (*ps).name);
//printf("%d\n", (*ps).age);
//printf("%s\n", s1.name);
//printf("%d\n", s1.age);
//printf("%s\n", s1.id);
return 0;
}
(十二)表达式求值
求值顺序由操作符的优先级和结合性决定;
1.隐式类型转换
C的整型算术运算总是至少以缺省整型类型的精度来进行的,为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升 。
1.1例如:
#include<stdio.h>
int main()
{
char a=3;
char b = 127;
char c = a + b;
printf("%d", c);
return 0;
}
结果是130吗?
我们发现计算机输出了-126这个值,分析在程序中体现:
#include<stdio.h>
int main()
{
char a=3;
a的2进制转换为
//00000000000000000000000000000011
//a只能放一个字节,规则是放00000011————a
char b = 127;
//00000000000000000000000001111111
//b只能放一个字节,规则是放01111111————b
char c = a + b;
//a+b
//00000011
//01111111
//整形提升是按照变量的数据类型的符号位来提升的,高位补充符号位,无符号数补充0.
//000000000000000000000000000000011
//000000000000000000000000001111111
//000000000000000000000000010000010
//10000010————c
//111111111111111111111111110000010————c的补码
//111111111111111111111111110000001————反码
//100000000000000000000000001111110————原码
//-126
printf("%d", c);
return 0;
}
1.2负数的整形提升:
char c1 = -1;
变量c1的二进制位(补码)中只有8个比特位: 1111111
整形提升的时候,高位补充符号位,即为1
提升之后的结果是: 11111111111111111111111111111111
1.3正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位: 00000001
整形提升的时候,高位补充符号位,即为0
提升之后的结果是: 00000000000000000000000000000001
1.4无符号整形提升,高位补0
1.5意义
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度 ,一般就是int的字节长度,同时也是CPU的通用寄存器的长度。 因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算。
典例1
int main()
{
char a = 0xb6;
short b = 0xb600;
//10110110
int c = 0xb6000000;
if (a == 0xb6)
printf("a");
if (b == 0xb600)
printf("b");
if (c == 0xb6000000)
printf("c");
return 0;
}
a,b整形提升之后,变成了负数
典例2
#include<stdio.h>
int main()
{
char c = 1;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(+c));
printf("%u\n", sizeof(!c));
return 0;
}
char原本是一个字节,但只要c发生表达式运算,就会发生整型提升。
2.算术运算
long double
double
float
unsigned long int
long int
int
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类 型,否则操作就无法进行
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运 算。这就是寻常算术转换。
但是算术转换要合理,不然会产生错误;
3.操作符的属性
1.优先级(相邻操作符运算优先级高的)
2.结合性(在优先级相同的情况下考虑结合性)
3.是否控制求值顺序
3.1问题表达式
a*b+c*d+e*f
计算顺序可能有:
a*b
c*d
a*b + c*d
e*f
a*b + c*d + e*f
或
a*b
c*d
e*f
a*b + c*d
a*b + c*d + e*f
c+ --c
不能确定+操作符的左操作数的获取在右操作数计算之前还是之后。
int main()
{
int i = 10;
i = i-- - --i * ( i = -3 ) * i++ + ++i;
printf("i = %d\n", i);
return 0;
}
非法表达式,在不同编译器的结果不同。
int fun()
{
static int count = 1; //static让1没被销毁
return ++count; } //2,3,4三种
int main()
{
int answer;
answer = fun() - fun() * fun();
printf( "%d\n", answer);//输出多少?
return 0; }
3个fun()的调用顺序不确定,结果不同
#include <stdio.h>
int main()
{
int i = 1;
int ret = (++i) + (++i) + (++i);
printf("%d\n", ret);
printf("%d\n", i);
return 0; }
在不同编译器下结果不同;
总结:要有唯一计算路径