操作符的分类
-算术操作符:+、-、*、/、%
-移位操作符:<<、>>
-位操作符:&、|、^
-赋值操作符:=、-=、+=、*=、/=、%=、<<=、>>=、&=、|=、^=
-单目操作符:!、++、--、&、+、-、*、%、/、~、sizeof、(类型)
-关系操作符:>、<、<=、>=、==、!=
-逻辑操作符:&&、||
-条件操作符:?:
-逗号表达式:,
-下标引用:[]
-函数调用:()
-结构成员访问:.、->
二进制和进制转换
我们知道在计算机中都是以二进制进行处理计算,而我们日常用的都是满10进1,也就是十进制;那么二进制就是满二进一,同理八进制与十六进制也是如此。那么他们之间是如何表达的呢?
//我们来看15这个数子在不同的进制中是如何表示的
//在二进制中:1111 1*2的3次方+1*2的2次方+1*2+1*2的零次方=15
//在八进制中:17 1*8+7*8的零次方=15
//在十进制中:15
//在十六进制中:F 在十六进制中,10~15为A、B、C、D、E、F
那么他们是怎么进行相互转换的呢?
1.二进制转十进制
如二进制1111转为十进制:1*(2^3)+1*(2^2)+1*(2^1)+1*(2^0)=15
2.十进制转为二进制
如十进制15转二进制:15/2=7……1
7/2=3……1
3/2=1……1
1/2=0……1
从下往上所得出的余数就是10进制转换后的二进制1111
3.二进制转八进制
如二进制的01101011换为八进制就是0153,将三个二进制数为一组,也就是01,101,011
4.二进制转为十六进制
如二进制的01101011换为十六进制是0x6b,四个二进制数为一组,0110,1011
原码、反码、补码
整数的二进制表示方法有原码、反码、补码
有符号整数表示方法有符号位和数值位两部分,最高位的1位是被当作符号位,其余的都是剩余位
符号位中1表示“负”,0表示“正”
那么正负数的三种表示方式有什么不同呢?
正整数的原、反、补码都是相同的
负整数的三种表示方法各不相同
原码:直接将数值按照正负数的形式翻译;
反码:将原码的符号位不变,其他位依次按位取反就是反码
补码:反码+1就得到补码
移位操作符
<<左移操作符;>>右移操作符
int main() {
//test1();
int num = 5;
int n1 = num << 1;
printf("n=%d\n", n1);
int n2 = num >> 1;
printf("n=%d ", n2);
return 0;
}
//得到的结果为n1=10,n2=2
//5:00000000 00000000 00000101
//左移一个后左边第一个0丢掉,在右边加一个0,00000000 00000000 00001010也就是10
//右边同理,把右边的第一个丢掉,左边加一个0
//需要注意的是不能移动负数位
位操作符
有按位与&,按位或|,按位异或^,按位取反~;他们的操作数必须是整数
int main(){
int n1 = -3;
int n2 = 5;
printf("%d\n", n1 & n2);
printf("%d\n", n1 | n2);
printf("%d\n", n1 ^ n2);
return 0;
}
//结果为5,-3,-8
对于-3的二进制原码:10000000 00000000 00000000 00000011
反码为 11111111 11111111 11111111 11111100
补码为: 11111111 11111111 11111111 11111101
对于5的二进制补码: 00000000 00000000 00000000 00000101
逻辑与&:对于补码中只有两个都为1结果才为1,则
00000000 00000000 00000000 00000101也就是5
逻辑或|:有1则为1
11111111 11111111 11111111 11111101
原码也就是-3 10000000 00000000 00000000 00000011
按位异或^:不一样的为1,一样的为0
11111111 11111111 11111111 11111000
反码 11111111 11111111 11111111 11110111
原码也就是-8 10000000 00000000 00000000 00001000
//在二进制计算中,用补码进行计算,用原码来表示
单目操作符
有!、++、--、&、*、+、-、~、sizeof、(类型)
其中&是取地址符号
逗号操作符
就是用逗号隔开的多个表达式,从左到右依次执行,整个表达式的结果就是最后一个表达式的结果
int a=1;
int b=2;
int c=(a>b,a=b+10,a,b=a+1);
//c为13,a=b+10,此时a为12,b=a+1也就是13,c取最后一个表达式的结果,所以c为13
下标访问[]、函数调用()
int arr[10]={1,2,3,4,5,6,7,8,9,10};
arr[9]=10;
//[]的两个操作数是arr和9
//操作数为:一个数组名+一个索引值(下标)
void test1() {
printf("hehe\n");
}
void test2(const char*str) {
printf("%s\n", str);
}
int main() {
test1();//()就是函数调用操作符
test2("hello");//()就是函数调用操作符
return 0;
}
//函数调用接受一个或者多个操作数,第一个操作数是函数名,剩余的操作数就是传递给函数的参数(test2中的hello)
结构成员访问操作符
结构是一些值的集合,这些值被称为成员变量,结构的每个成员变量可以是不同类型的变量
其中struct是关键字
//结构体的声明
struct str{
char name[20];
int age;
};//注意分号不能丢掉
//结构体变量的定义和初始化
//变量的定义
struct str {
int x;
int y;
}p1;//声明类型的同时定义变量p1
struct str p2;//定义结构体变量p2
struct str p3 = { 10,20 };//初始化
结构体成员的直接访问是通过操作符.访问的,点操作符接收两个操作数
struct Point {
int x;
int y;
}p = { 1,2 };
int main() {
printf("x:%d y:%d\n", p.x, p.y);
return 0;
}
//输出结构为x:1 y:2
使用方式:结构体变量.成员名
结构体的间接访问是得到一个指向结构体的指针
struct Point1 {
int x;
int y;
};
int main() {
struct Point1 p = { 3,4 };
struct Point1 *ptr = &p;
ptr->x = 10;
ptr->y = 20;
printf("x=%d y=%d\n", ptr->x, ptr->y);
return 0;
}
//输出结果为x=10 y=20
使用方式:结构体指针->成员名