C语言操作符详解

【揭秘!】这里有你从未听过的独特见解,快来点赞关注,开启智慧之旅 

目录

1.操作符的分类

2.二进制和进制转换

2.1 二进制转十进制

 2.2  十进制转二进制

2.3 二进制转八进制

2.4  二进制转十六进制

3.原码、反码、补码

4.位移操作符

4.1左移操作符

4.2右移操作符

5.位操作符:&、|、^、~

6.单目操作符

7.逗号表达式

8.下标访问 [ ] 、函数调用 ( )

8.1   [  ] 下标引用操作符

8.2  ( ) 函数调用操作符

9.结构成员访问操作符

 9.1 结构体

 9.2结构体的声明

 9.3结构体变量的定义和初始化

9.4结构体成员访问操作符 

10.操作符的属性:优先级、结合性


1.操作符的分类

算术操作符:+   -   *   /   %

位移操作符: <<    >> 

位操作符    : &   |   ^

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

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

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

逻辑操作符: &&    || 

条件操作符: ?   : 

逗号表达式:

下表引用   : [  ] 

函数调用  :  (  ) 

结构体成员访问: .    -> 

2.二进制和进制转换

        我们经常可以听到2进制、8进制、10进制、16进制这样讲法,在我们日常中,最常见的便是10进制。我们知道10进制是每逢10进1。类似的2进制每逢2进1,8进制每逢8进1,16进制每逢16进1。

举个例子:数值15的各种进制的表达式

1   15的2进制:1111

2   15的8进制:17

3   15的10进制:15

4   15的16进制:F

2.1 二进制转十进制

其实10进制的123表示的值是一百二十三,因为10进制的每一位是权重的,10进制的数字从右向左是个位、十位、百位......,分别每一位的权重是:10^0,10^1,10^2......

如下图:

2进制和10进制是类似的,只不过2进制的每一位权重,从右向左是:2^0,2^1,2^2......

举例:2进制的1101

 2.2  十进制转二进制

2.3 二进制转八进制

        8进制的数字每一位是由0~7的数字组成,各自写成2进制,最多有3个2进制位就够了,比如7的二进制是111,所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位换算一个8进制位,剩余不够3个2进制位的直接进行换算

例如:2进制的01101011,换成8进制:0153, 0数字开头的数字会被当做8进制

2.4  二进制转十六进制

        16进制的数字每一位是由0~9,a~f 的数字组成,各自写成2进制,最多有4个2进制就够了,比如 f 的二进制是1111,所以在2进制转换成16进制数的时候,从2进制序列中右边低位开始向左每4个2进制位换算一个16进制,剩余不够4个二进制位的直接换算

例如:2进制的01101011,换成16进制:0x6b,16进制表示的时候面加0x

3.原码、反码、补码

整数的二进制表示方法有三种,即原码、反码、补码

无符号整数的三种表达式均有符号位和数值位两部分,2进制序列中,最高的1位是被当做符号位,剩余的都是数值位。

:符号位都是用0表示“正”,用1表示“负”

1.正整数的原、反、补码都相同。

2.负整数的三种表示方法各不相同。

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

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

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

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

为什么对于整形来说:数据存放在内存中,其实是存放的补码

        因为在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器),此外补码与原码互相转换,其运算过程是相同的,不需要额外的硬件电路。 

4.位移操作符

<<   左移操作符

>>   右移操作符

:位移操作符的操作数只能是整数

4.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;
}

4.2右移操作符

 移位规则:首先右移运算分为两种:

1.逻辑右移:左边用0填充,右边丢弃

2.算术右移:左边用原该值的符号位填充,右边丢弃

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

逻辑右移1位演示: 

 算术右移1位演示:

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

5.位操作符:&、|、^、~

1   &        //按位与     :有0则0,双1才1

2   |         //按位或     :有1则1,双0才0

3   ^        //按位异或  :相同取0,不同取1

4   ~       //按位取反   

:它们的操作数必须是整数。 

代码举例:

#include <stdio.h>
int main()
{
	int num1 = -3;
	int num2 = 7;
	printf("%d\n", num1 & num2);
	printf("%d\n", num1 | num2);
	printf("%d\n", num1 ^ num2);
	printf("%d\n", ~0);
	return 0;
}

6.单目操作符

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

单目操作符的特点是只有一个操作数,在单目操作符中只有 & 和 * 没有介绍,这两个操作符在指针的时候进行讲解。

7.逗号表达式

1   exp1,exp2,exp3,...expN

逗号表达式,就是用逗号隔开的多个表达式。

逗号表达式 ,从左向右依次执行,整个表达式的结果是最后一个的表达式的结果

举例:

#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, b = a + 1);
	printf("%d", c);
}

//最后输出 13

8.下标访问 [ ] 、函数调用 ( )

8.1   [  ] 下标引用操作符

操作数:一个数组名+一个索引值

1    int arr[10];    //创建数组 

2    arr[9] =10;    //实用下标引用操作符

3    [  ]  的两个操作数是 arr 和 9 

8.2  ( ) 函数调用操作符

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

#include <stdio.h>


void test1()
{
    printf("chixiu\n");
}
void test2(const char* str)
{
    printf("%s\n", str);
}
int main()
{
    test1();                  //这里的( )就是作为函数调用操作符
    test2("hello bit.");  //这里的( )就是函数调用操作符
    return 0;
}

9.结构成员访问操作符

 9.1 结构体

C语言已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类型哈是不够的。假如我想和描述学生,描述一本书,这时单一的内置类型是不行的。描述一个学生需要姓名、年龄、学号、身高、体重等;描述一本书需要作者、出版社、定价等。C语言为了解决这个问题,增加了结构体这种定义的数据类型,让程序员可以自己创建合适自己的类型。

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

 9.2结构体的声明

struct  tag

{

        member-list;

}variable-list;

描述一个学生:

struct Stu
{
	char name[20]; //名字
	int age;       //年龄
	char sex[5];   //性别
	char id[20];   //学号
};   //分号不能丢

 9.3结构体变量的定义和初始化

//代码1:变量的定义
struct Point
{
	int x;
	int y;
}p1;              //声明类型的同时定义变量p1
struct Point p2;  //定义结构体变量p2
// p1  p2  都是全局变量

//代码2:初始化
struct Point p3 = { 10,20 };

struct Stu       //类型声明
{
	char name[15];  //名字
	int age;        //年龄
};


struct Stu s1 = { "zhangsan",20 };				//初始化
struct Stu s2 = { .age = 20,.name = "list" };	//指定顺序初始化

//代码3
struct Node
{
	int data;
	struct Ponit p;
	struct Node* next;
}n1 = { 10,{4,5},NULL };            //结构体嵌套初始化

struct Node n2 = { 20,{5,6},NULL }; //结构体嵌套初始化

9.4结构体成员访问操作符 

        结构体成员的直接访问     使用方式:结构体变量.成员名

结构体成员的直接访问是通过点操作符( . )访问的。点操作符接受两个操作数。如下所示:

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

int main()
{
	printf("x: %d  y: %d\n", p.x, p.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.操作符的属性:优先级、结合性

C语言的操作符有两个重要的属性:优先级、结合性,这两个属性决定了表达式求值的计算顺序。

优先级:指的是,如果一个表达式包含多个运算符,哪个运算符应该优先执行。各种运算符的优先级是不一样的。

结合性:如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就看结合性了,则根据运算符是左结合还是右结合,决定执行顺序。大部分运算符是左结合(从左到右执行),少数运算符是右结合(从右到左执行),比如赋值运算符( = )。

 参考:https://zh.cppreference.com/w/c/language/operator_precedence

用心呈现,只为遇见更好的你!点赞关注,让我们的博客陪伴你成长

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赤秀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值