目录
逻辑操作符
>
>=
<=
!=
==
注意:不要将 ‘ == ’ 写成 ‘ = ’
逻辑操作符:
&&
||
例11.&与&&的差异:
例12. 这个题值得思考
在&&的判断中如果一边位假(0)那么程序就会停止向后面判断。所以++b与d++并没有执行
在 || 的判断中如果一边为真,则停止继续向下判断。(如:++a || b++ || c)
补充:
条件操作符(三目操作符)
a>b?a:b
逗号表达式
a,b,c,d,.....n
逗号表达式整体的值等于最后一个表达式的值
例13 思考题
int main() {
int a = 0;
int b = 1, c = 2;
a = (a = b, b += c, c--);
printf("case1:%d\n", a);
a = 0,b = 1, c = 2;
a = (a < 0, a++, b = a);
printf("case2:%d\n", a);
a = 0, b = 1, c = 2;
a = (a<0, b<a);
printf("case3:%d\n", a);
a = 0, b = 1, c = 2;
if (a = b + 1, c = a / 2 - 1, c == 0)
printf("case4:%d\n", c);
}
另一种代码书写方式:
//一般情况
a = get_val();
count_val(a);
while (a > 0) {
//业务处理
a = get_val();
count_val(a);
}
//应用逗号表达式
while (a = get_val(), count_val(a), a > 0) {
//业务处理
}
合理应用逗号表达式可以简化代码。
下标引用,函数调用和结构成员
1. [ ] 下标引用操作符
对于数组 arr[5] = {1,2,3,4,5}
我们一般的用法是:
arr[0],arr[1],arr[2].....其中arr[0]就代表访问数组中第一个元素,arr[1]代表访问第二个以此类推
学习了指针之后我们知道:
arr代表数组首元素的地址。
arr[0],arr[1],arr[2]...我们可以改写成:*arr,*(arr+1),*(arr+2)..... (*arr可以理解为*(arr+0))
进一步思考:
*(arr+1)可以改写成*(1+arr)
那么arr[1]可否写成1[arr]呢?答案是肯定的。
所以我们就有了一下结论:
1[arr] == arr[1] == *(arr+1) == *(1+arr)
事实上,无论哪一种写法,程序再最终编译的时候都会转化为:*( arr+1)
2. ( ) 函数调用操作符
例14.有参数调用
int add(int x, int y){
return x+y;
}
int main(){
int a = 1;
int b = 2;
printf("%d",add(a,b));
}
例15.无参数调用
void test(){
printf("看到这里的都是人才!!!\n");
}
int main(){
test();
}
3.访问一个结构的成员
. (结构体.成员名)
-> (结构体指针 -> 成员名)
例16.
struct Stu{
char name[20];
int age;
}stu;
int main(){
stu = {"张三",20};
struct Stu *ps = &stu;
//下面三种写法都是正确的
printf("%s %d\n",stu.name,stu.age);
printf("%s %d\n",(*ps).name,(*ps).age);
printf("%s %d\n",ps->name,ps->age);
}
表达式求值
隐式类型转换
- C的整型算术运算总是至少以缺省整型类型的精度来进行的。
- 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
整型提升的意义:
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度 一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长 度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算。
整型提升方法:
正数的整型高位补充0 负数补充1
例17.整型提升示例
注:char是有符号的
补充:字符类型的反码(1字节)及其表示的值
总结:
char 的值范围是:-128 ~ 127
unsigned char 值的范围是:0 ~ 255
例18.整型提升在程序中的证明
int main()
{
char a = 0x41;
char b = 0xFF;//0xFF -> 255 11111111
int c = 0xb6000000;
if (a == 0x41) {//正数原码补码一致,整型提升补码不变
printf("a\n");
printf("%d %c\n", a, a);
}
if (b == 0xFF) {
printf("b\n");
}
//在判断 b==0xFF 时 要对b进行整型提升
//b 11111111 -> 11111111 11111111 11111111 11111111 而 0xEF的补码依然是11111111 所以这两个补码时不同的
printf("%d %c\n", b, b);
//输出时 依然要对b进行整型提升
// 11111111 -> 补码:11111111 11111111 11111111 11111111
//反码:11111111 11111111 11111111 11111110
//原码:10000000 00000000 00000000 00000001 即:-1
if(c==0xb6000000)
printf("c\n");
return 0;
}
例子20.整型提升的再一次证明
算数转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类 型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
long double 8byte
double 8byte
float 4byte
unsigned long int 4byte
long int 4byte
unsigned int 4byte
int 4byte
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
附:各类型变量在内存中占的字节(32位)
int main() {
printf("%d\n", sizeof(char));//1
printf("%d\n", sizeof(int));//4
printf("%d\n", sizeof(unsigned int));//4
printf("%d\n", sizeof(long));//4
printf("%d\n", sizeof(unsigned long));//4
printf("%d\n", sizeof(long long int));//8
printf("%d\n", sizeof(float));//4
printf("%d\n", sizeof(double));//8
printf("%d\n", sizeof(long double));//8
}
操作符属性
1. 操作符的优先级
2. 操作符的结合性
3. 是否控制求值顺序
附录:
(图片来自比特科技)
以上就是操作符(下)的全部内容,欢迎大家指教!有什么问题可以在评论区题问。
对您有帮助不妨点一个赞哦