操作符详解
1、操作符
1)算术操作符
+ - * / %
a.除了%之外,其余的几个操作符都可以作用于整数和浮点数
b.对于/操作符,如果两个操作数都是整数,则执行整数除法,只要有浮点数则执行浮点数除法
c.%的两个操作符必须是整数,返回整除之后的余数
2)移位操作符(二进制)
<< //左移操作符
>> //右移操作符
a.左移操作符移位规则:左边抛弃,右边补0
b.右移操作符移位规则:
*算术右移:右边抛弃,左边补原符号位
逻辑右移:右边抛弃,左边补0
c.对于移位运算符,不能移动负数位
3)位操作符(二进制)
& //按位与
| //按位或
^ //按位异或
eg.统计一个数二进制位中‘1’的个数(举例:5)
#include <stdio.h>
int main()
{
int a = 5;
//101
int b = 1;
//001
int count = 0; //原数字中1的个数
int c = 0;
do
{
c = a & b;
if (c == 1)
{
count++;
}
a = a >> 1;
} while (a);
printf("%d", count);
return 0;
}
4)赋值操作符
= 及其变式(比如+=)
5)单目操作符
! //逻辑反操作
- //负值
+ //正值
& //取地址
sizeof //操作符的类型长度(单位:字节) -->sizeof是一个操作符,不是函数,并且括号中的表达式不参与运算
~ //对一个数的二进制按位取反
-- //前置、后置--
++ //前置、后置++
* //解引用操作符
(类型) //强制类型转换
sizeof举例:
void test1(int arr[])
{
printf("%d/n", sizeof(arr));
}
void test2(char ch[])
{
printf("%d/n", sizeof(ch));
}
int main()
{
int arr[10] = {0};
char ch[10] = {0};
printf("%d/n", sizeof(arr)); //40
printf("%d/n", sizeof(ch)); //10
test1(arr); //8
test2(ch); //8
return 0;
}
6)关系操作符
> < >= <= != ==
7)逻辑操作符
&& //逻辑与
|| //逻辑或
注意区分逻辑与/或和按位与/或的区别
举例:
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++; //a先使用后++,使用前为0,&&后不计算
printf("a=%d/nb=%d/nc=%d/nd=%d/n", a, b, c, d);
//打印:1 2 3 4
a=1;
i = a++ || ++b || d++; //a为真,||后的不计算
printf("a=%d/nb=%d/nc=%d/nd=%d/n", a, b, c, d);
//打印:2 2 3 4
8)条件操作符
exp1 ? exp2 : exp3
9)逗号表达式
exp1, exp2, exp3……expn
从左向右计算,整个表达式的结果是最后一个表达式的结果
10)下标引用、函数调用和结构成员
a.下标引用操作符[]:
操作数:一个数组名+一个索引值
int arr[10]; //创建数组
arr[9]=10; //实用下标引用操作符
//[]的操作数是arr和9
b.函数调用操作符():
接受一个或者多个操作数,第一个操作数是函数名,剩余的操作数是传递给函数的参数
c.访问一个结构的成员.:
.结构体.成员名
->结构体指针->成员名
举例:
struct book
{
char name[20];
int price;
};
int main()
{
struct book Book = {"C lan", 20};
//方法一
printf("书名:%s/n", Book.name);
printf("价格:%d/n", Book.price);
//方法二
struct book *pb = &Book;
printf("书名:%s/n", (*pb).name);
printf("价格:%d/n", (*pb).price);
//方法三
printf("书名:%s/n", pb->name);
printf("价格:%d/n", pb->price);
}
2、表达式求值
表达式求值的顺序的一部分是由操作符的优先级和结合性决定,同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。
3、隐式类型转换
C语言的整型算术运算总是至少以缺省整型类型的精度来进行的。
为了获得这个精度,表达式中的字符(char)和短整型(short)操作数在使用之前被转换为普通整型,这种转换称为整型提升。
举例:
char a,b,c;
c=a+b;
b和c的值被提升为普通整型,然后再执行加法运算,加法运算完成之后,结果将被截断,之后再存储到a当中。
整型提升的意义:表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int字节长度,同时也是CPU的通用寄存 器的长度。因此,即使两个char类型的变量相加,在CPU内执行时实际上也要先转换成CPU内整型操作数的标准长度。通用CPU难以实现两个8比特 字节直接相加运算,所以,表达式中所有可能小于int长度的整型值,都必须先转为int或者unsigned int,然后才能送入CPU去执行运算。
整型提升的具体方法:按照变量的数据类型的符号位来提升
//负数的整型提升
char c1 = -1; //变量c1的二进制位(补码)中只有8个比特位:11111111
//因为char为有符号的char
//在整型提升的时候,高位补充符号位,即11111……11111(32个1)
//正数的整型提升
char c2 = 1; //变量c1的二进制位(补码)中只有8个比特位:00000001
//因为char为有符号的char
//在整型提升的时候,高位补充符号位,即00……00(31个0)1
//无符号数的整型提升,高位补0
char a = 3;
//00000000000000000000000000000011 --整型提升
//00000011 --截断
char b = 127;
//00000000000000000000000001111111 --整型提升
//01111111 --截断
char c = a + b;
//00000000000000000000000000000011
//00000000000000000000000001111111
//00000000000000000000000010000010 --相加
//10000010 -- c
//11111111111111111111111110000010 --补码
//11111111111111111111111110000001 --反码
//10000000000000000000000001111110 --原码
printf("%d",c); //打印整型c
整型提升例子
char c =1;
printf("%u",sizeof(c)); //1
printf("%u",sizeof(+c)); //4
printf("%u",sizeof(-c)); //4
printf("%u",sizeof(!c)); //4
4、算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作就无法进行。
下面的层次体系称为寻常算术转换:
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作符的类型在上表中排名较低,那么首先要转换为另外一个操作数的类型之后才能执行运算。
6、操作符的属性
复杂表达式的求值有3个影响因素:
1)操作符优先级
2)操作符的结合性
3)是否控制求值顺序
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/149399.html