【C语言】超详解,让你C语言成功入门(五)——操作符

目录

  • 1.算术操作符
  • 2.移位操作符
    • 2.1左移操作符<<
    • 2.2右移操作符>>
  • 3.位操作符
  • 4.赋值操作符
  • 5.单目操作符
    • 5.1单目操作符介绍
    • 5.2sizeof 和 数组
  • 6.关系操作符
  • 7.逻辑操作符
  • 8.条件操作符(三目操作符)
  • 9.逗号表达式
  • 10.下标引用、函数调用和结构体
  • 11.表达式传值
      • 11.1 隐式类型转换
      • 11.2 算术转换
      • 12.3 操作符的属性
  • 12.优先级

1.算术操作符

操作符含义范例结果
+加法x+yx和y的和
减法x–yx和y的差
*乘法x * yx和y的积
/除法x / yx和y的商
%求余x%yx除以y的余数

注意:
(1)运算符%要求左右两个运算数据必须为整型数据,如5%2的值为3。
(2)相除时,结果为整数,小数部分舍去。但若除数或被除数中有一个为负值,则舍入的方向是不固定的。如5/3=1,但–5/3在有的计算机得到的结果是–1,而有的计算机上的结果是–2。C99规定采取 “向零取整” 的方法,即取整后向零取整。
(3)字符型数据可以和数值型数据进行运算,因为字符型数据在计算机中是用一个字节的整型数(ASCII码)表示的。如 ‘A’+1在进行运算时会把A的ASCII码65与1相加,最后得出结果就是66。

2.移位操作符

移的是二进制(补码)。

整数的二进制有三种表示法:

  • 原码
  • 补码
  • 反码

浮点数还有一种移码,移码通常用于表示浮点数的阶码。(计算机组成原理会讲,咱们这里先做了解)

整数在内存中存储的是补码。

编码正数负数
真值+(二进制)–(二进制)
原码高位补0,符号位补0高位补0,符号位补1
反码与原码相同原码的符号位不变,其他位按位取反(0→1,1→0)
补码与原码相同原码取反+1(反码+1)
移码符号位变1,其他位与补码相同符号位变0,其他位与补码相同

例:演示只用8位,最高一位为符号位(已加粗)

编码5–5
真值+0101–0101
原码0000010110000101
反码0000010111111010
补码0000010111111011
移码1000010101111011

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

2.1左移操作符<<

规则:左边抛弃,右边补0

例1:5<<1
在这里插入图片描述
5的补码变为了00001010,原码为00001010,其二进制数为1010,转换为十进制:10。所以5左移一位后变成了10。

例2:–5<<1
在这里插入图片描述
–5的补码变为了11110100,反码为11110011,原码为10001100,其二进制数为–1100,转换为十进制:–12。所以–5左移一位后变成了–12。

2.2右移操作符>>

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

  1. 逻辑移位
    左边用0填充,右边丢弃
  2. 算术移位
    左边用原该值的符号位填充,右边丢弃
    在这里插入图片描述

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

int num = 10;
num>>-1;//错误

3.位操作符

位操作符含义范例
&按位与x & y
按位或x ∣ y
^按位异或x ^ y

注:他们的操作数必须是整数。

#include <stdio.h>
int main()
{
    int num1 = 1;
    int num2 = 2;
    num1 & num2;
    num1 | num2;
    num1 ^ num2;
    return 0;
}

4.赋值操作符

(1)简单赋值运算
“ = ”的作用是将赋值符号右边的对象的值赋值给左边的对象。例:x = 9;
把值9赋给x,实际意义是将10存储到x的存储单元中。
此处“ = ”是赋值符,而非等于号。等于号是“ == ”,例如:if(x==10),意思是如果x等于10。

注:①10 = x;是无效语句。赋值运算符的左侧必须是一个运算对象,此对象的值可以改变。10是整数常量,不能改变其值,不能给常量赋值。
②若参与赋值运算的运算对象的数据类型不同,则右边对象的数据类型会被转换成左侧对象的类型。
③可以连续赋值:x = y = 10;

(2)复合赋值运算
在赋值运算符前加上其他运算符,例如在“ = ” 前加上“ + ”,运算符就变成了复合运算符“ += ”。
例:x += 10;
相当于 x = x+10;
其他算术运算符也可以与赋值运算符组合成复合赋值运算符。

5.单目操作符

5.1单目操作符介绍

单目操作符含义范例
逻辑反操作!a
+正号+x
负号–x
&取地址&a
sizeof操作数的类型长度(以字节为单位)sizeof(arr)
~对一个数的二进制按位取反~a
++前置、后置++++a 或 a++
– –前置、后置 – –– – a 或 a – –
*间接访问操作符(解引用操作符)*p
(数据类型)强制类型转换(int)a
#include <stdio.h>
int main()
{
    int a = -10;
    int *p = NULL;
    printf("%d\n", !2);
    printf("%d\n", !0);
    a = -a;
    p = &a;
    printf("%d\n", sizeof(a));
    printf("%d\n", sizeof(int));
    printf("%d\n", sizeof a);//这样写行不行?
    printf("%d\n", sizeof int);//这样写行不行?
    return 0;
}

自增运算符++
当 i 变量每次都要加1时,可写为 i++,或++i
相当于 i = i +1;

自减运算符 – –
当 i 变量每次都要减1时,可写为 i – – 或 – – i
相当于 i = i – 1;

自增、自减运算符的结合性是“ 从右到左 ”。x * y++ 相当于x * (y++),而并非是(x * y)++。

//++和--运算符
//前置++和--
#include <stdio.h>
int main()
{
    int a = 10;
    int x = ++a;
    //先对a进行自增,然后对使用a,也就是表达式的值是a自增之后的值。x为11。
    int y = --a;
    //先对a进行自减,然后对使用a,也就是表达式的值是a自减之后的值。y为10;
    return 0;
}
//后置++和--
#include <stdio.h>
int main()
{
    int a = 10;
    int x = a++;
    //先对a先使用,再增加,这样x的值是10;之后a变成11;
    int y = a--;
    //先对a先使用,再自减,这样y的值是11;之后a变成10;
    return 0;
}

5.2sizeof 和 数组

一般形式:sizeof(运算对象)
圆括号可有可无,但是当运算对象是数据类型是,必须加上圆括号。
例如:sizeof(int), sizeof x, sizeof(x), sizeof 34, sizeof(34)
sizeof的结合性是“ 从右到左 ”。

如果运算对象是表达式,那表达式将不会被执行,只会输出此表达式的数据类型所占的字节数。

#include<stdio.h>
int main()
{
    int a = 12,b = 1;
    printf("%zd\n",sizeof(a = a+b);
    printf("a = %d\n",a);
    return 0;
}

运算结果:
4
a = 12

sizeof运算的结果是一个无符号整数类型。C99新增了转换说明%zd用于输出 sizeof 运算结果的值。如果编译器不支持使用%zd,可以使用 %u 或 %lu 代替 %zd。

#include <stdio.h>

void test1(int arr[])
{
    printf("%d\n", sizeof(arr));//(2)
}

void test2(char ch[])
{
    printf("%d\n", sizeof(ch));//(4)
}

int main()
{
    int arr[10] = {0};
    char ch[10] = {0};
    printf("%d\n", sizeof(arr));//(1)
    printf("%d\n", sizeof(ch));//(3)
    test1(arr);
    test2(ch);
    return 0;
}

问:
(1)、(2)两个地方分别输出多少?
(3)、(4)两个地方分别输出多少?

答:
(1)、(2)两个地方分别输出多少?——40、4/8
(3)、(4)两个地方分别输出多少?——10、4/8
(1)、(3)= 数组大小 × 数据类型所占字节
(2)、(4)= 指针大小(4/8字节)

(2)、(4)为什么是指针大小?

test1(arr) 和 test2(ch) 其实传的都是地址,又可以写成test1(&arr)test2(&ch),那函数接收地址则是用的指针,指针大小为4byte或8byte(取决于编译器)。
具体的我们下一篇指针部分详细讲解。

6.关系操作符

关系操作符含义范例
<小于x<y
>大于x>y
<=小于等于x<=y
>=大于等于x>=y
==等于x==y
!=不等于x!=y

关系运算符的结合性是“ 从左到右 ”。a < b > c <= d 与( (a < b) > c) <= d 相同。

注意:浮点数之间进行比较时,尽量只使用 “ < ” 和 “ > ”。因为浮点数使用近似值表示的,这会导致逻辑上相等的两数却不相等。

7.逻辑操作符

逻辑运算符含义范例
&&逻辑与x && y
∣∣逻辑或x ∣∣ y
!逻辑非!x

在逻辑运算中,如果运算对象的值为非0,则认为是逻辑真,否则认为是逻辑假。真用 1 表示,假用 0 表示。

逻辑非
例:int a=5;
!a的结果为0,因为a不等于0。

ab!a!ba&&ba∣∣b

运算符 ! 的结合性是“ 从右到左 ”,而&&和 || 的结合性是“ 从左到右 ”。

在多个&&(或 ||)相连时,因结合性是从左到右,故当左边的运算对象为假(或真),停止运算。

8.条件操作符(三目操作符)

条件运算符的一般形式为:
表达式1 ?表达式2 :表达式3

条件运算符 ?:的功能是:在计算表达式1后,如果值为真(非0),则计算表达式2,并将表达式2的值作为整个表达式的结果;如果表达式1的值为假(0),则计算表达式3,并将表达式3的结果作为整个表达式的值。

x=10;
if(x > 8)
   y=20;
else
   y=10;

那我们可以用条件表达式来处理:

y = (x > 8) ? 20 : 10;

因x=10,比8大。故y的值为20,如果x所赋的值小于等于8,y的值赋为10。

9.逗号表达式

逗号运算符(,)用于将两个表达式连接时。如:
a+b , a+c
一般形式:表达式1 , 表达式2
求解过程:先求表达式1,再求表达式2。整个逗号表达式的值是表达式2的值。

一个逗号表达式又可以与另一个表达式组成一个新的逗号表达式。所以逗号表达式的一般形式又可拓展为:
表达式1, 表达式2, 表达式3, … , 表达式 n

注意:逗号也用作分隔符。下面代码中的逗号都是分隔符,而非逗号运算符。

int a,b;
printf("%d %d",a,b);

10.下标引用、函数调用和结构体

  1. []下标引用操作符
    操作数:一个数组名 + 一个索引值
int arr[10];//创建数组
arr[9] = 10;//实用下标引用操作符。
[ ]的两个操作数是arr和9
  1. ()函数调用操作符
    接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
#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. 访问结构体成员变量
  • . :结构体 . 成员名
  • -> :结构体指针 -> 成员名
#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;//结构成员访问
}
int main()
{
    struct Stu stu;
    struct Stu* pStu = &stu;//结构成员访问
 
    stu.age = 20;//结构成员访问
    set_age1(stu);
 
    pStu->age = 20;//结构成员访问
    set_age2(pStu);
    return 0;
}

11.表达式传值

表达式求值的顺序一部分是由操作符的优先级和结合性决定。

同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

11.1 隐式类型转换

C的整型算术运算总是至少以缺省整型类型的精度来进行的。

为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

整型提升的意义:

  • 表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。

    因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。

    通用CPU(general-purposeCPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int
    或 unsigned int,然后才能送入CPU去执行运算。

//实例1
char a,b,c;
...
a = b + c;

b和c的值被提升为普通整型,然后再执行加法运算。加法运算完成之后,结果将被截断,然后再存储于a中。

如何进行整体提升呢?

整形提升是按照变量的数据类型的符号位来提升的

  • 负数的整形提升
    char c1 = -1;
    变量c1的二进制位(补码)中只有8个比特位:
    1111111
    因为 char 为有符号的 char
    所以整形提升的时候,高位补充符号位,即为1
    提升之后的结果是:
    11111111111111111111111111111111
  • 正数的整形提升
    char c2 = 1;
    变量c2的二进制位(补码)中只有8个比特位:
    00000001
    因为 char 为有符号的 char
    所以整形提升的时候,高位补充符号位,即为0
    提升之后的结果是:
    00000000000000000000000000000001
  • 无符号整形提升,高位补0

11.2 算术转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。

long double
double
float
unsigned long int
long int
unsigned int
int

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。

警告:
但是算术转换要合理,要不然会有一些潜在的问题。

float f = 3.14;
int num = f;//隐式转换,会有精度丢失

12.3 操作符的属性

复杂表达式的求值有三个影响的因素。

  1. 操作符的优先级
  2. 操作符的结合性
  3. 是否控制求值顺序。

两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。

12.优先级

在这里插入图片描述
运算符优先级图源:https://www.wendangwang.com/doc/75d2728bbb843fed98536860

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/219411.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于DotNetty实现一个接口自动发布工具 - 通信实现

基于 DotNetty 实现通信 DotNetty : 是微软的 Azure 团队&#xff0c;使用 C#实现的 Netty 的版本发布。是.NET 平台的优秀网络库。 项目介绍 OpenDeploy.Communication 类库项目,是通信相关基础设施层 Codec 模块实现编码解码 Convention 模块定义约定,比如抽象的业务 Handle…

华为手环 8 五款免费表盘已上线,请注意查收

华为手环 8&#xff0c;作为一款集时尚与实用于一体的智能手环&#xff0c;不仅具备强大的功能&#xff0c;还经常更新的表盘样式&#xff0c;让用户掌控时间与健康的同时&#xff0c;也能展现自己的时尚品味。这不&#xff0c;12 月官方免费表盘又上新了&#xff0c;推出了五款…

批量AI创作文案的工具,批量AI创作文章的软件

人工智能&#xff08;AI&#xff09;的应用不断拓展&#xff0c;其中批量AI创作逐渐成为许多文本创作者和企业编辑的热门选择。面对海量的文章需求&#xff0c;批量AI创作工具能够高效、快速地生成大量文本内容&#xff0c;从而减轻创作者的工作负担。本文将专心分享批量AI创作…

Linux last命令教程:如何查看用户的登录和注销历史(附案例详解和注意事项)

Linux last命令介绍 last命令在Linux中用于显示自文件/var/log/wtmp创建以来所有用户的登录和注销列表。可以给出一个或多个用户名作为参数&#xff0c;以显示他们的登录&#xff08;和注销&#xff09;时间和主机名。 Linux last命令适用的Linux版本 last命令在大多数Linux…

高温老化房稳定性、应用领域

高温老化房控制系统的稳定性主要有四点: 1. 温度控制:控制系统确保老化室内的温度在整个老化试验过程中保持稳定并在期望的范围内。这种稳定性对于准确可靠的测试结果至关重要。 2. 湿度控制:控制系统同时保持老化室内湿度水平稳定。这一点很重要&#xff0c;因为某些材料或产…

UE5 - 把ArchvizExplorer项目改造成自己的数字孪生项目 - 开发记要

参考&#xff1a; https://blog.csdn.net/qq_17523181/article/details/133853099 https://blog.csdn.net/qq_17523181/article/details/134455597 1. 安装项目 https://www.unrealengine.com/marketplace/zh-CN/product/archviz-explorer https://karldetroit.com/archviz-exp…

inBuilder低代码平台新特性推荐-第十三期

各位知乎的友友们&#xff0c;大家好~ 今天来给大家介绍一下inBuilder低代码平台社区版中特性推荐系列第十三期——登录配置&#xff01; inBuilder低代码平台内置了多种表单登录方式&#xff1a;用户名密码、AD域、数字证书。用户可以通过系统的登录页面进行登录。登录界面样…

提升--22---ReentrantReadWriteLock读写锁

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 ReadWriteLock----读写锁1.读写锁介绍线程进入读锁的前提条件&#xff1a;线程进入写锁的前提条件&#xff1a;而读写锁有以下三个重要的特性&#xff1a; Reentran…

从浅入深掌握进阶结构体(C语言)

前言 这一期我们将继续讲解结构体的知识&#xff0c;还没有看过上一期的小伙伴一定要赶紧去学习哦。 上一期&#xff0c;冲鸭&#xff01; 那么话不多说我们开始今天的学习吧&#xff01; 文章目录 1,结构体的自引用2,匿名结构体3,位段4,结构体的传参5,尾声 1,结构体的自引用 …

Docker篇之docker部署harbor仓库

一、首先需要安装docker step1&#xff1a;安装docker #1、安装yun源 yum install -y yum-utils #2、配置yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 如果上面源不稳定的话&#xff0c;更换为下列的aliyun源 yu…

Redis数据结构之压缩列表

压缩列表是Redis为节约内存而开发的&#xff0c;是由一系列特殊编码的连续内存块组成的顺序型数据结构。一个压缩列表可以包含任意多个节点&#xff0c;每个节点可以保存一个字节数组或者整数值。 压缩列表构成 zlbytes: 记录整个压缩列表占用的内存字节数&#xff0c;对压缩列…

预付费用电管理系统在商场及宿舍的应用

安科瑞电气股份有限公司 上海嘉定 201801 【摘要】本文主要讨论了预付费用电管理系统软、硬件的构建方法&#xff0c;软件系统的各个模块设计&#xff0c;以及软、硬件设计过程中解决的主要问题。1联5系8电2话171微3信5同2号2 【关键词】预付费电能表硬件设计软件设计 引言 …

linux基础五:linux 系统(进程状态+进程优先级+调度和切换+环境变量)

linux 系统 一.进程状态&#xff1a;1.睡眠状态(sleep)&#xff1a;2.磁盘休眠状态(disk sleep)&#xff1a;3.停止状态(stoped --- T)&#xff1a;4.死亡状态&#xff1a;5.控制状态&#xff08;t&#xff09; 二.僵尸进程和孤儿进程&#xff1a;1.僵尸状态&#xff1a;2.孤儿…

基于51单片机风扇控制器系统设计

**单片机设计介绍&#xff0c;基于51单片机风扇控制器系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的风扇控制器系统是一种用于控制风扇转速和温度管理的电子设备。下面是一个简单的设计介绍&#xff1a;…

Python小案例:打印10以内的素数

解析 1、利用循环控制范围&#xff08;1,100&#xff09; 2、通过循环判断素数 3、利用标记位法进行打印素数 代码 #求1——100之间的素数 for i in range(2,101):# 设置标记位is_primeNumis_primeNum Truefor j in range(2,i):if i%j 0:# print(f"{i}不是素数"…

第三方支付原理

1.什么是第三方支付 所谓第三方支付&#xff0c;就是一些和各大银行签约、并具备一定实力和信誉保障的第三方独立机构提供的交易支持平台。在通过第三方支付平台的交易中&#xff0c;买方选购商品后&#xff0c;使用第三方平台提供的账户进行货款支付&#xff0c;由第三方通知卖…

04.里氏替换原则(Liskov Substitution Principle)

暴论&#xff1a;一般的&#xff0c;如果一个富二代不想着证明自己&#xff0c;那么他一辈子都会衣食无忧。 一言 里氏替换原则想告诉我们在继承过程中会遇到什么问题&#xff0c;以及继承有哪些注意事项。 概述 这是流传较广的一个段子&#xff1a; “一个坐拥万贯家财的富二…

博客文章SEO:提升博客排名和吸引更多读者的方法来啦!

互联网发展到现在&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;一直发挥着不可替代的作用。搜索引擎的流量往往更加定向&#xff0c;来自搜索引擎的流量转化率更高&#xff0c;可以帮助企业更好地实现销售和推广目标。因此&#xff0c;通过合理的SEO策略&#xff0c;你…

Data Linked UI

DataLinkedUl是一个Unity框架,它允许您在为您的应用程序创建用户界面时实现专业的数据驱动方法。使用此资产,您可以创建灵活的基于瓦片的任意大小的复杂接口系统。 核心功能: 灵活性-允许适应和调整数据变化,允许各种结构和功能配置,而不需要对现有系统进行重大破坏。 可伸…

跨境独立站反向代购系统是什么?如何搭建?

淘宝代购是近年兴起的一种购物模式&#xff0c;是帮国外客户购买中国商品。主要是通过万邦 科技的外贸代购系统&#xff0c;把淘宝、天猫等电商平台的全站商品通过API 接入到你的网站 上&#xff0c;瞬间就可以架设一个有数亿产品的大型网上商城&#xff0c;而且可以把这些中文…