1.算术操作符
+ - * / %
加减法和数学中的一样 , 其中乘除法对于整数的结果是整数,对于浮点数的结果是浮点数,但要注意结果打印的格式和精度缺失。%是取余的意思,如a%b,得到a的余数,%两边的a和b必须为整数。
2.移位操作符
(不适用于浮点数)
左移操作符 <<
右移操作符 >>
左移操作符移位规则:在32个比特位中补码左边越位抛弃,右边不足补零。
右移操作符移位规则:
首先右移运算分为两种:
1.逻辑移位(基本不用此规则):在32个比特位中补码右边越位抛弃,左边不足补零。
2.算数移位(基本采用此规则):在32个比特位中补码右边越位抛弃,左边不足用原符号补上。
如下:
补充:<< 左移操作有乘二的效果,>> 右移操作有除二的效果,对整数和负数皆适用,请读者自行体会。
警告:对于移动运算符,不要移动负数位,这个是标准未定义的。如:
int num = 10;
num>>-1;//error
补充:计算机内的的数据是按补码运算的,但是是按原码的结果打印电脑屏幕上的。
3.位操作符
& 按位与 | 按位或 ^ 按位异或
注意:它们的操作数必须是整数。
例如:a的补码为 00000101
b的补码为 00010110
a & b的规则为:两数补码同位比较,都为1取1,其余都取零,即a&b得到 00000100
a | b的规则为:两数补码同位比较,有1就取1,都为零才取零,即a | b得到 00010111
a ^ b的规则为:两数补码同位比较,相同取零,不同取1,即a ^ b得到 00010011
4.赋值操作符
=
例如: int a = 10;赋值操作符可以连续赋值。
复合赋值:+= -= *= /= %= >>= >>= &= |= ^=
如a+=1为 a=a+1。其余同理。
5.单目操作符
! 逻辑反操作
- 负值
& 取地址
- 正值
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
– 前置,后置–
++ 前置,后置++
- 间接访问操作符(解引用操作符)
(类型) 强制类型转换
规则:
!: 对非0的数取反为0,对0取反为1.
& : 若arr是数组名,&arr表示整个数组,若swap是函数名则&swap没有语法错误。int a =1; &a得到的是a的地址
注意:sizeof(不是函数)
int a= 10;
int b=0;
int arr[10]={0};
printf("%d",sizeof a);//可以这样写
printf("%d",sizeof int);//不可以这样写
printf("%d",sizeof (int));//可以
printf("%d",sizeof(arr));//为40,表示整个数组
printf("%d",sizeof(int [10]);//为40,可以这样写
printf("%d",sizeof(&arr);//为4,表示数组首元素地址字节大小
printf("%d",sizeof(b=a+5);//为4,sizeof()内的表达式不计算,所以b还是0
~ :对一个数的二进制数取反,如:0001010取反得到 1110101
++ - - :分为前置和后置区别如下:
#include<stdio.h>
int main()
{
int a=1;
int b=0;
b=a++;//a先自增,表达式为a运算之前的值
printf("%d %d",a,b);//打印得到2 1
return 0;
}
#include<stdio.h>
int main()
{
int a=1;
int b=0;
b=++a;//a先自增,表达式为a运算之后的值
printf("%d %d",a,b);//打印得到2 2
return 0;
}
前置- -和后置用法同上
6.解引用操作符
int a = 10;
int p = &a; //这里是定义p是指针的意思,不是解引用操作
p = 20; //这里的才是解引用操作
*&a = 20; //这样写编译不会出错
补充:若有 *00x0018ff44;//语法错误,因为00x0018ff44是一个单纯的十六进制数字,无法对它解引用,可以改成 *(int *)00x0018ff44,强制转化成int型的地址就可以了。
强制转换
如:
int a=10;
printf("%f",(float)a/3);结果为3.333333,()里面输入直接想转化的类型
###6.关系操作符
< >= <=
!= //用于测试不相等
== //用于测试相等
常见陷阱:
x=get_value();
if(x=5) //实际是将x赋值为5,程序必定执行,注意=和==的区别
7.逻辑操作符
&& 逻辑与
|| 逻辑或
#include <stdio.h>
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++&&++b&&d++;//只有a参与运算
//i = a++||++b||d++;//只有a和b参与运算
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
程序的结果为: 1 2 3 4,是不是很吃惊,其实对于&&两边只要有0就停止运算,从左到右运算,a++这个表达式为0,那就停止运算,不管++b和d++了,所以就是这个结果。那么对于i = a++||++b||d++,结果为1 3 3 4,a++为0,++b为3,||两边有真就为真,停止运算,结果就为1 3 3 4.
8.条件操作符
exp1? exp2 : exp3
int max = 0;
int a = 5;
int b = 4;
max = a > b ? a:b;//若a>b为真,表达式的值为a,否则为b
9.逗号表达式
exp1 ,exp2, exp3,…
//代码1
int a = 1; int b = 2; int c = (a>b, a=b+10, a,
b=a+1);//逗号表达式从左到右依次执行,整个表达式的结果是最后一个表达式的结果,即c = 13.
10.下表引用,函数调用和结构成员
[] //下表引用:
int arr[10];
arr[9] = 10;//实现下表引用操作符
若有arr[4] = 5和4[arr] = 5;两表达式效果相同,编译不会出错
() //函数调用操作符
有两个操作数,分别为函数名和函数调用的参数
如:test(void) test2(a)
3.访问一个结构的成员
. //结构体名.成员名
-> //结构体指针->成员名 如下:
#include <stdio.h>
struct Stu
{
char name[10];
int age;
char sex[5];
double score;
};
void set_age1(struct Stu stu)
{
stu.age = 18;//结构体名.成员名
}
void set_age2(struct Stu* pStu)
{
pStu->age = 18;//结构体指针->成员名
}