『C语言初阶』第八章 -隐式类型转换规则

news2024/11/24 3:11:00

在这里插入图片描述

前言

今天小羊又来给铁汁们分享关于C语言的隐式类型转换规则,在C语言中类型转换方式可分为隐式类型转换显式类型转换(强制类型转换),其中隐式类型转换是由编译器自动进行,无需程序员干预,今天小羊课堂说的就是关于隐式类型转换,隐式类型转换分为两种情况:整型提升和算术转换


一、隐式类型转换的规则

在c语言中,自动类型转换遵循以下规则:

  1. 若参与运算量的类型不同,则先转换成同一类型,然后进行运算。
  2. 转换按数据长度增加的方向进行,以保证精度不降低。如int型和long型运算时,先把int量转成long型后再进行运算。
    a、若两种类型的字节数不同,转换成字节数高的类型
    b、若两种类型的字节数相同,且一种有符号,一种无符号,则转换成无符号类型
  3. 所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算。
  4. char型和short型参与运算时,必须先转换成int型。
  5. 在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换为左边量的类型。如果右边量的数据类型长度比左边长时,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入。

二、整型提升

C的整型算术运算总是至少以缺省整型类型的精度来进行的,为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。

原理

有符号补符号位,无符号位无脑补0

1.负数的整型提升

高位补充符号位,即补1

char a=-1;
变量a的二进制位(补码)中只有8个比特位:
11111111
因为char是有符号的char
所以整型提升的时候,补符号位,即补1
提升结果:
11111111 11111111 11111111 11111111

2.正数的整型提升

高位补充符号位,即补0

char a=1;
变量a的二进制位(补码)中只有8个比特位:
00000001
因为char是无符号的char
所以整型提升的时候,补符号位,即补0
提升结果:
00000000 00000000 00000000 00000001

3.无符号的整型提升

无符号整型提升,高位补0(无符号只有正数)


三、整型提升实例

例1:

#include <stdio.h>
int main()
{
	char a = 5, b = 127;
	char c = a + b;
	int d = a + b;
	printf("c=%d\n", c);
	printf("d= %d", d);
	return 0;
}

运行结果:

c=-124
d=132

分析:

char a=5
0000 0101 --> a=5
char b=127
0111 1111 --> b=127
因为参与了运算,并且char类型的精度小于int类型,所以这里进行整型提升:
00000000 00000000 00000000 00000101 --> a=5
00000000 00000000 00000000 01111111 --> b=127
00000000 00000000 00000000 10000100 --> c=132

//1:>

将结果存入类型为char的变量c中,c只能存储8位,所以保留结果最后81000 0100 --> c=132
由于char类型也是有正负的,且计算结果是以补码形式,转化为原码
补码:1000 0100
反码:1000 0011
原码:1111 1100 --> -124
原码值为-124

//2:>

运算还是先整型提升再运算,二进制同上,最后结果存放到int类型的b中,所以直接就是132

例2:

#include<stdio.h>
int main()
{
	char a = 0xb6;
	short b = 0xb600;
	int c = 0xb6000000;
	if (a == 0xb6)
		printf("a");
	if (b == 0xb600)
		printf("b");
	if (c == 0xb6000000)
		printf("c");
	return 0;
}

运行结果:

c

分析:

a=0xb6
整型提升前:10110110 
整型提升后:11111111 11111111 11111111 10110110 可以直接看出这是一个负数的补码
b=0xb600
整型提升前:10110110 00000000
整型提升后:11111111 11111111 10110110 00000000 可以直接看出这也是一个负数的补码
c=0xb6000000
无需整型提升,故结果为真

例3:

#include<stdio.h>
int main()
{
	char c = 1;
	printf("c=%u\n", sizeof(c));//%u按无符号整形unsigned int打印
	printf("c=%u\n", sizeof(+c));
	printf("c=%u\n", sizeof(-c));
	return 0;
}

运行结果:

c=1
c=4
c=4

分析:

sizeof(c),c没有参与运算,故就是求char类型大小
sizeof(+c)sizeof(-c),c参与运算,整型提升为int,故就是求int类型大小

四、算术转移

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

//从高到低
long double
double
float
unsigned long int
long int
unsigned int
int

注:
如果在同一运算中操作数类型不同,等级低的要往等级高的转换。
算术转换要合理,否则会存在潜在的问题

例1:

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

例2:

#include<stdio.h>
int main()
{
	unsigned char a = 0;
	unsigned char b = 255;
	unsigned char c = 255;
	a = b + c;
	printf("a = %d\n", a);
	return 0;
}

运行结果:

a = 254

分析:

b和c的值都需要提升为整型,再执行加法运算

b\c:>
整型提升前:11111111
整型提升后:11111111 11111111 11111111 11111111

 11111111 11111111 11111111 11111111 --> b
 11111111 11111111 11111111 11111111 --> c
111111111 11111111 11111111 11111110 --> a
 结果保留最后的811111110 --> 补码
 由于是无符号char类型,那么原反补一样
 原码也是11111110 即为254

总结

发生转换的原因:
硬件:CPU寄存器的比特位是统一的,将内存中的数据放入寄存器中就会发生隐式转换
软件:C语言的操作符对多个操作数进行操作时,必须保证其类型一致


五、操作符的属性

1.操作符

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

  1. 操作符的优先级。决定了有多个操作符和多个操作数时,先执行哪部分。
  2. 操作符的结合性。当优先级相同,多个或单个操作符之间从左向右执行还是从右向左执行。
  3. 是否控制求值顺序。特定的某些表达式在进行求值,根据不同的条件产出不同的求值过程。

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

2.操作符优先级

操作符优先级,从上往下,重点的

操作符结合性是否控制求值顺序
()N/A
,L-R
->L-R
++L-R
L-R
++R-L
R-L
*R-L

3.问题表达式

表达式1

a*b + c*d + e*f

注释:代码1在计算的时候,由于乘法的优先级比+的优先级高,只能保证的乘法计算是比+早,但是优先级并不能决定第三个*比第一个+早执行。

所以表达式的计算机顺序就可能是:

a*b
c*d
a*b + c*d
e*f
a*b + c*d + e*f
或者:
a*b
c*d
e*f
a*b + c*d
a*b + c*d + e*f

表达式2

非法表达式1

int main()
{
	int i = 10;
	i = i-- - --i * (i = -3) * i++ + ++i;
	printf("i = %d\n", i);
	return 0;
}

非法表达式2

int fun()
{
     static int count = 1;
     return ++count; }
int main()
{
     int answer;
     answer = fun() - fun() * fun();
     printf( "%d\n", answer);//输出多少?
     return 0; }

这两个表达式,铁汁们要好好思考这为什么是非法的,不懂得可以私信小羊哦

总结:

我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式一定存在问题


好了,今天小羊分享的C语言的隐式类型转换规则就讲到这里了,欢迎大家评论区留言~~

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阻塞和非阻塞,同步和异步

文章目录 典型的一次IO的两个阶段IO多路复用是同步还是异步&#xff1f; 典型的一次IO的两个阶段 数据就绪和数据读写 同步&#xff1a;需要应用程序自己操作 IO多路复用是同步还是异步&#xff1f; epoll也是同步的 具体数据读取还是通过应用程序自己完成的 只有使用了特…

快速开发平台 WebBuilder 的功能特点

WebBuilder 是一款强大&#xff0c;全面和高效的应用开发和运行平台。基于浏览器的集成开发环境&#xff0c;智能化的设计&#xff0c;能轻松完成常规桌面应用和面向手机等的移动应用开发。高效、稳定和可扩展的特点&#xff0c;适合复杂企业级应用的运行。跨平台、数据库和浏览…

线性回归例子

转自&#xff1a;https://www.cnblogs.com/BlairGrowing/p/15061912.html 刚开始接触深度学习和机器学习&#xff0c;由于是非全日制&#xff0c;也没有方向感&#xff0c;缺乏学习氛围、圈子&#xff0c;全靠自己业余时间瞎琢磨&#xff0c;犹如黑夜中的摸索着过河。 只是顺…

易服客工作室:WordPress是什么?初学者的解释

目录 什么是WordPress&#xff1f; WordPress可以制作什么类型的网站&#xff1f; 谁制作了WordPress&#xff1f;它已经存在多久了&#xff1f; 谁使用 WordPress&#xff1f; 白宫网站 微软 滚石乐队 为什么要使用 WordPress&#xff1f; WordPress 是免费且…

【不支持发行版本 5】错误解决

说明&#xff1a;启动项目报下面的错误&#xff0c;不支持发行版本 5 解决&#xff1a;在pom文件中添加下面这两行配置&#xff0c;修改成你自己安装的jdk版本 <properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target&g…

TienChin 新建业务菜单

首先是移动菜单&#xff0c;参考下图将菜单移动到下图结构&#xff1a; 我这里将系统监控&#xff0c;系统工具都移动到了系统管理下面&#xff0c;并且排了个序&#xff0c;将多级菜单放在了一起&#xff0c;这样看起来更加的清晰。 修改一下系统管理(100)与TienChin健身官网(…

Blazor:组件生命周期和刷新机制详解

文章目录 前言生命周期子组件设置事件刷新为什么传入非基础元素&#xff0c;会强制刷新 自动刷新逻辑如何解决委托事件强制刷新问题 前言 对于组件化来说&#xff0c;生命周期是必须掌握的知识&#xff0c;只有掌握了生命周期才能更好的去设置数据的变化。 Blazor 生命周期 微…

99. for循环练习题-3种方式输出0-9

【目录】 文章目录 99. for循环练习题-3种方式输出0-91. for循环和while循环的区别2. 输出 0~(n-1)的数字2.1 基础代码2.2 自定义函数代码2.3 异常处理语句代码 【正文】 99. for循环练习题-3种方式输出0-9 1. for循环和while循环的区别 for循环和while循环都用于重复执行特定…

AI Infra工具关键能力解析:数据准备、模型训练、模型部署与整合

在预训练大模型时代,我们可以从应用落地过程里提炼出标准化的工作流,AI Infra的投资机会得以演绎。传统ML时代AI模型通用性较低,项目落地停留在“手工作坊”阶段,流程难以统一规范。而大规模预训练模型统一了“从0到1”的技术路径,具备解决问题的泛化能力,能够赋能“从1到…

WiFi小工具homedale,可以切换同名WiFi节点

有一个很小众的需求&#xff0c;就是多个路由器组网时候&#xff0c;PC有时不会自动切换同名WiFi&#xff0c;homedale这个工具可以满足手动切换需求 这个界面可以看到所有节点列表&#xff0c;可以看到有很多同名的 可以选择自己想要的那个&#xff0c;比如信道/信号强度&am…

avd(emulator)设置代理以及与pc互访

默认pc127.0.0.1是还回ip&#xff0c;模拟器使用127.0.0.1指向了自己&#xff0c;模拟器使用10.0.2.2指代pc地址&#xff0c;这点在官方文档有说明可以查看,所以想要挂代理抓包就需要为模拟器设置代理为10.0.2.2 安卓模拟器设置代理 前提&#xff1a;本机开启了代理如&#xf…

nodejs+vue+elementui健康饮食美食菜谱分享网站系统

本系统采用了nodejs语言的vue框架&#xff0c;数据采用MySQL数据库进行存储。结合B/S结构进行开发设计&#xff0c;功能强大&#xff0c;界面化操作便于上手。本系统具有良好的易用性和安全性&#xff0c;系统功能齐全&#xff0c;可以满足饮食分享管理的相关工作。 语言 node.…

05 mysql innodb page

前言 最近看到了 何登成 大佬的 "深入MySQL源码 -- Step By Step" 的 pdf 呵呵 似乎是找到了一些 方向 之前对于 mysql 方面的东西, 更多的仅仅是简单的使用[业务中的各种增删改查], 以及一些面试题的背诵 这里会参照 MySQL Internals Manual 来大致的看一下 i…

06_Hudi案例实战

本文来自"黑马程序员"hudi课程 6.第六章 Hudi案例实战 6.1 案例架构 6.2 业务数据 6.2.1 消息数据格式 6.2.2 数据生成 6.3 七陌数据采集 6.3.1 Apache Flume 是什么 6.3.2 Apache Flume 运行机制 6.3.3 Apache Flume 安装部署 6.3.4 Apache Flume 入门程序 6.3.5 七…

springboot项目重启的shell命令

大家好&#xff0c;我是雄雄&#xff0c;微信公众号&#xff1a;雄雄的小课堂&#xff0c;欢迎关注。 前言 我们都知道&#xff0c;springboot项目启动的时候&#xff0c;需要如下过程&#xff1a; 查找 服务的进程id杀掉该进程启动服务 并且每一步都有对应的shell命令&…

torch.cat() stack()函数使用说明,含实例及运行结果

torch.cat和stack函数使用说明&#xff0c;含实例及运行结果 torch.cat() 函数torch.cat() 函数定义参数及功能二维数据实例解释参数dim0参数dim1参数dim-1 torch.stack() 函数torch.stack() 函数定义参数及功能二维数据实例解释参数dim0参数dim1参数dim2参数dim-1 参考博文及感…

关于Neo4j的使用及其基本命令

关于Neo4j的使用 文章目录 关于Neo4j的使用1、启动方式2、创建新节点&#xff0c;节点内有属性3、创建关系4、查询节点5、查询关系6、删除两个节点的关系7、删除节点8、删除某个标签的全部关系9、某个节点添加属性10、删除节点某个属性 1、启动方式 进入bin目录&#xff1a; …

成人自考-英语二-大纲要求及考试题型及分值详细介绍

感谢内容提供者&#xff1a;金牛区吴迪软件开发工作室 文章目录 一、大纲要求二、考试题型及分值1. 总览2. 样卷【2015年】(1) 阅读判断(2)阅读选择(3)概括段落大意(4)补全句子(5)填句补文(6)填词补文(7)完形补文(8)短文写作 一、大纲要求 二、考试题型及分值 1. 总览 2. 样卷…

视野狭窄--程序员的解决之道

为什么会发生这种情况&#xff1f; 这是我学到的最艰难的一课&#xff1a;辛勤工作和意图并不等同于商业影响力。我太专注于对给定问题的出色解决&#xff0c;而没有停下来考虑我是否在解决正确的问题。我在工程师身上投入的所有时间并没有使我们解决的问题变得更重要。你的主…

射频入门知识-混频器-1

5.4混频电路-视频_哔哩哔哩_bilibili ​​​​​​​