【C语言有这个就够了】四.操作符详解(2)

时间:2022-10-11 19:58:09

(七)关系操作符

​<  <=  >  >=  !=  ==​

都挺简单,唯一注意=和==

(八)逻辑操作符

逻辑与  &&

逻辑或  ||

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

【C语言有这个就够了】四.操作符详解(2)

&&的特点是只要前面运算为假了,后面的运算全部不进行。(因为都为假)

所以当计算到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;
}

【C语言有这个就够了】四.操作符详解(2)

(九)条件操作符---三目操作符

​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这个值,分析在程序中体现:

【C语言有这个就够了】四.操作符详解(2)

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

【C语言有这个就够了】四.操作符详解(2)

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

【C语言有这个就够了】四.操作符详解(2)

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

在不同编译器下结果不同;


总结:要有唯一计算路径