C语言:操作符的学习总结

在编写代码的时候需要各种操作符配合使用才能够达到目的,下面分享一下C语言的操作符。

一、操作符分类

算数操作符:+、-、*、/、%

移位操作符:>>、<<

位操作符:&、|、^

赋值操作符:=、+=、-=、*=、/=、%=、<<=、>>\、&=、|=、^=

单目操作符:!、++、--、&、*、+、-、~、sizeof、(类型)

关系操作符:>、>=、<、<=、==、!=

逻辑操作符:&&、||

条件操作符:? :

逗号表达式:,

下标引用:[ ]

函数调用:( )

结构成员访问:. 、->

二、二进制和进制转换

由于部分操作符与二进制有关,所以先来了解一下二进制和其他进制的转换。常见进制有二进制、十进制、八进制、十六进制,与十进制作比较,十进制是满十进一,那么二进制就是满二进一,八进制就是满八进一,十六进制就是满十六进一,另外十六进制超过9的数用字母表示,一到十五就是1 2 3 4 5 6 7 8 9 A B C D E F,并且在C语言中16进制的数值之前要写0x,8进制的数值之前写0。二进制每一位都是由0和1组成的比如:10110.

1、二进制和十进制的转换

(1)二进制转十进制

其实10进制的123表⽰的值是⼀百⼆⼗三,为什么是这个值呢?其实10进制的每⼀位是有权重的,10 进制的数字从右向左是个位、⼗位、百位....,分别每⼀位的权重是10的0次方、10的1次方、10的2次方。

2进制和10进制是类似的,只不过2进制的每⼀位的权重,从右向左是2的0次方、2的1次方、2的2次方。

那么二进制转换为10进制,比如1101,就等于1*1+0*2+1*4+1*8=13。

(2)十进制转二进制

将十进制数转换为二进制数可以用短除法,比如数字125,将125除以2得商62余1,然后再将62除以2商31余1,再31除以2商15余1,再15除以2商7余1,再7除以2商3余1,再3除以2商1余1,再1除以2商0余1,结束除法,在将所有余数按照逆序写出就是二进制的125,即1111101。

2、二进制转八进制和十六进制

(1)二进制转八进制

8进制的数字每⼀位是 0~7 的,0~7 的数字,各⾃写成2进制,最多有3个2进制位就足够了,比如7的二进制是111,所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位会换算⼀ 个8进制位,剩余不够3个2进制位的直接换算。 如:2进制的 01101011,换成8进制:0153,0开头的数字,会被当做8进制。

(2)二进制转十六进制

16进制的数字每⼀位是0~9, a~f 的,0~9, a~f的数字,各⾃写成2进制,最多有4个2进制位就⾜够了, 比如 f 的二进制是1111,所以在2进制转16进制数的时候,从2进制序列中右边低位开始向左每4个2进 制位会换算⼀个16进制位,剩余不够4个⼆进制位的直接换算。 如:2进制的01101011,换成16进制:0x6b,16进制表示的时候前面加0x。

三、原码、反码、补码

整数的2进制表示方法有三种,即原码、反码和补码 有符号整数的三种表示方法均有符号位和数值位两部分,2进制序列中,最高位的1位是被当做符号 位,剩余的都是数值位。 符号位都是用0表示“正”,用1表示“负”。

注意:正整数的原、反、补码都相同。 负整数的三种表示方法各不相同。

原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。

反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。

补码:反码+1就得到补码。

补码得到原码也是可以使用:取反,+1的操作。

无符号整数的三种 2 进制表示相同,没有符号位,每⼀位都是数值位,并且对于整形来说:数据存放内存中其实存放的是补码。

四、移位操作符

移位操作符分为左移操作符和右移操作符,并且移位操作符的操作数只能是整数。

1、左移操作符

移位规则:左边抛弃、右边补0。比如:

#include <stdio.h>
int main()
{
    int num = 10;
    int n = num << 1;
    printf("n = %d\n", n);
    printf("num = %d\n", num);
    return 0;
}

将数字n左移一位,是对n的二进制数补码进行操作的,因为整数在内存中是以补码形式存储的:

//int n=10
//二进制的n
//00000000 00000000 00000000 00001010
//n<<1,将最左边的0丢弃,再在最右边补一个0
//00000000 00000000 00000000 00010100

2、右移操作符

右移操作符分为逻辑右移和算数右移:

(1)逻辑右移:左边用0填充,右边丢弃。

(2)算数右移:左边⽤原该值的符号位填充,右边丢弃。

​#include <stdio.h>
int main()
{
    int num = -1;
    int n = num >> 1;
    printf("n = %d\n", n);
    printf("num = %d\n", num);
    return 0;
}

​

如果是逻辑右移:

​//int n=-1
//二进制的n的补码
//11111111 11111111 11111111 11111111
//n>>1,将最右边的1丢弃,再在最左边补一个0
//01111111 11111111 11111111 11111111

​

如果是算数右移:

​​//int n=-1
//二进制的n的补码
//11111111 11111111 11111111 11111111
//n>>1,将最右边的1丢弃,再在最左边补一个1,
//同样如果右边丢弃的是0,就在左边补0
//1111111 11111111 11111111 11111111

​

​

注意:对于移位运算符,不要移动负数位,这个是标准未定义的。比如:

int num = 10;
num >> -1;//error

五、位操作符

位操作符有:

&:按位与

|:按位或

^:按位异或

~:按位取反

位操作符的操作数也必须是整数。

看如下代码:

#include <stdio.h>
int main()
{
    int num1 = -3;
    int num2 = 5;
    printf("%d\n", num1 & num2);
    printf("%d\n", num1 | num2);
    printf("%d\n", num1 ^ num2);
    printf("%d\n", ~0);
    return 0;
}
//int num1=-3  int num2=5
//-3
//原码 10000000 00000000 00000000 00000011
//反码 11111111 11111111 11111111 11111100
//补码 11111111 11111111 11111111 11111101
//5的原反补都一样
//补码 00000000 00000000 00000000 00000101
//将两者的补码每一位进行与操作
//最后的答案也是补码
//     00000000 00000000 00000000 00000101 ->5

则num1 & num2 就是5。

​//int num1=-3  int num2=5
//-3
//原码 10000000 00000000 00000000 00000011
//反码 11111111 11111111 11111111 11111100
//补码 11111111 11111111 11111111 11111101
//5的原反补都一样
//补码 00000000 00000000 00000000 00000101
//将两者的补码每一位进行或操作
//最后的答案也是补码
//     11111111 11111111 11111111 11111101 ->-3

​

则num1 | num2 就是-3。

异或的操作是相同为0,相异为1。

​​//int num1=-3  int num2=5
//-3
//原码 10000000 00000000 00000000 00000011
//反码 11111111 11111111 11111111 11111100
//补码 11111111 11111111 11111111 11111101
//5的原反补都一样
//补码 00000000 00000000 00000000 00000101
//将两者的补码每一位进行异或操作
//最后的答案也是补码
//     11111111 11111111 11111111 11111000 ->-8

​

​

则num1 ^ num2 就是-8。对于~0取反就是0变为1,1变为0。

那么如何运用位操作符,并且不创建第三个变量来实现两个整数的交换。这里可以使用异或操作符,根据异或的交换律和相同为0相异为1的特点,那么a^a=0,0^a=a,有:

#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;
    a = a ^ b;
    b = a ^ b;//b=a^b=a^b^b=a^0=a
    a = a ^ b;//a=a^b=a^a^b=0^b=b
    printf("a = %d b = %d\n", a, b);//实现交换
    return 0;
}

六、单目操作符

单目操作符有:!、++、--、&、*、+、-、~ 、sizeof、(类型)。单目操作符的特点是只有⼀个操作数。

七、逗号表达式

逗号表达式,就是用逗号隔开的多个表达式。 逗号表达式,从左向右依次执行。整个表达式的结果是最后⼀个表达式的结果。

//代码1
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);//逗号表达式
//c就是13

//代码2
if (a = b + 1, c = a / 2, d > 0)

//代码3
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、下标引用操作符[ ]

操作数:函数名+下标

int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[ ]的两个操作数是arr和9。

2、函数调用操作符( )

接受⼀个或者多个操作数:第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。

​#include <stdio.h>
void test1()
{
    printf("hehe\n");
}
void test2(const char *str)
{
    printf("%s\n", str);
}
int main()
{
    test1(); //这⾥的()就是作为函数调⽤操作符。
    test2("hello bit.");//这⾥的()就是函数调⽤操作符。
    return 0;
}

​

九、结构成员访问操作符

在学习这个操作符之前要先了解什么事结构体。

1、结构体

结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如: 标量、数组、指针,甚⾄是其他结构体。

(1)结构体声明

struct tag
{
    member-list;
}variable-list;

如果要用结构体描述一个学生:

struct Stu
{
    char name[20];//名字
    int age;//年龄
    char sex[5];//性别
    char id[20];//学号
}; //可以在这里创建一个变量也可以不创建

(2)结构体变量的定义和初始化

struct Stu //类型声明
{
    char name[15];//名字
    int age; //年龄
    int score;//成绩
}s3;//可以在结构体末尾创建一个全局变量

struct Stu s1 = {"zhangsan", 20,88};//初始化

int main()
{
    struct Stu s2 = {"lisi", 18,86};
    return 0;
}

(3)结构体成员访问操作符

结构体成员的直接访问是通过点操作符(.)访问的。点操作符接受两个操作数,在访问这个成员进行打印或者指定顺序初始化的时候会用到。如下所示:

#include <stdio.h>
struct Point
{
    int x;
    int y;
}p1 = {1,2};

int main()
{
    struct Point p2=(.y=20,.x=9);//指定顺序初始化
    printf("x: %d y: %d\n", p1.x, p1.y);
    return 0;
}

有时候我们得到的不是⼀个结构体变量,而是得到了⼀个指向结构体的指针,就可以间接访问,通过(->)操作符来访问。结构体指针->成员名。

#include <stdio.h>
struct Point
{
    int x;
    int y;
};
int main()
{
    struct Point p = {3, 4};
    struct Point *ptr = &p;
    ptr->x = 10;
    ptr->y = 20;
    printf("x = %d y = %d\n", ptr->x, ptr->y);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值