C语言入门系列:数据类型转换

文章目录

  • 一,自动类型转换
    • 1,赋值运算
      • 1.1,浮点数赋值给整型变量-不安全
      • 1.2,整数赋值给浮点数变量-安全
      • 1.3,窄类型赋值给宽类型-安全
      • 1.4,宽类型赋值给窄类型-不安全
    • 2,混合类型的运算
      • 2.1,整形和浮点数混合
      • 2.2,不同的浮点数类型混合
      • 2.3,不同的整数类型混合
    • 3,整数类型的运算
    • 4,函数
  • 二,强制类型转换

在这里插入图片描述

当不同数据类型的数据出现在同一个表达式中时,就会涉及数据类型转换,C语言中的数据类型转换有两种:

  • 自动类型转换
  • 强制类型转换

类型转换可能是安全的,即不会丢失数据;也可能是不安全的,即出现丢失数据的情况。

窄类型转换为宽类型,是安全的,不会丢失数据。

宽类型转换为窄类型,是不安全的,虽然不是百分百丢失数据,但有丢失数据的可能。

一,自动类型转换

自动类型转换是指在特点情况下,编译器将一种数据类型自动转换为另一种类型,自动类型转换可能是安全的,也可能是不安全的,即可能出现数据丢失。

1,赋值运算

赋值运算符左右两边的数据类型不一致时,会以变量的类型为准,将右边的值转成变量的类型。

1.1,浮点数赋值给整型变量-不安全

浮点数赋予整型变量时,C语言的转换过程简单粗暴,保留整数部分,丢弃小数部分。

int x = 3.14159627;

如上,变量x被声明为整型,然后赋一个double类型值。

编译器会把3.14159627转为整形,小数部分0.14159627会被丢弃(注意,不是四舍五入),保留整数3,3被赋值给变量x,因此变量x的值是3。

显然,这种情况下的自动类型转换导致数据丢失,是不安全的类型转换,我们在编写代码时,要避免类似的赋值语句,左右两边的类型一致才是最佳实践。

1.2,整数赋值给浮点数变量-安全

整型赋值给浮点数变量时,会自动转为浮点数。

float y = 12 * 2;

上面示例中,变量y的值不是24,而是24.0,因为等号右边的整数自动转为了浮点数。

C语言中的浮点数遵循了IEEE 754标准,使用科学计数法来存储浮点数,其数组范围被整形要大得多,所以整形赋值给浮点数,不会出现数据丢失,是安全的自动类型转换。

1.3,窄类型赋值给宽类型-安全

字节宽度较小的整数类型,赋值给字节宽度较大的整数变量时,会发生类型提升,即窄类型自动转为宽类型。

比如,char或short类型赋值给int类型,会自动提升为int。

char x = 100;
int i = x + y;

上面示例中,变量x的类型是char,由于赋值给int类型,所以会自动提升为int。

1.4,宽类型赋值给窄类型-不安全

字节宽度较大的类型,赋值给字节宽度较小的变量时,会发生类型降级,自动转为后者的类型。这时可能会发生截断,系统会将移除的高位二进制,从而出现意料之外的情况。

int i = 321;
char ch = i; // ch 的值是 65 (321 % 256 的余值)

上面例子中,变量ch是char类型,宽度是8个二进制位。

变量i是int类型,将i赋值给ch,后者只能容纳i(二进制形式为101000001,共9位)的后八位,前面多出来的二进制位被丢弃,保留后八位就变成了01000001(十进制的65,相当于字符A)。

之前介绍的浮点数赋值给整型变量,也属于宽类型自动转换为窄类型,也会发生截断,丢弃小数部分。

double pi = 3.14159;
int i = pi; // i 的值为 3

上面示例中,i等于3,pi的小数部分被截去了。

2,混合类型的运算

不同类型的值进行混合计算时,必须先转成同一个类型,才能进行计算。转换规则如下:

2.1,整形和浮点数混合

整数与浮点数混合运算时,整数转为浮点数类型,与另一个运算数类型相同。

3 + 1.2 // 4.2

上面示例是int类型与float类型的混合计算,int类型的3会先转成float的3.0,再进行计算,得到4.2。

2.2,不同的浮点数类型混合

运算时,宽度较小的类型转为宽度较大的类型,比如float转为double,double转为long double。

2.3,不同的整数类型混合

运算时,宽度较小的类型会提升为宽度较大的类型。

比如short转为int,int转为long等,有时还会将带符号的类型signed转为无符号unsigned。

下面例子的执行结果,可能会出人意料。

int a = -5;
if (a < sizeof(int)do_something();

上面示例中,变量a是带符号整数,sizeof(int)是size_t类型,这是一个无符号整数。

按照规则,signed int 自动转为 unsigned int,所以a会自动转成无符号整数4294967291(转换规则是-5加上无符号整数的最大值,再加1),导致比较失败,do_something()不会执行。

所以,最好避免无符号整数与有符号整数的混合运算。因为这时 C 语言会自动将signed int转为unsigned int,可能不会得到预期的结果。

3,整数类型的运算

两个相同类型的整数运算时,或者单个整数的运算,一般来说,运算结果也属于同一类型。

但是有一个例外,宽度小于int的类型,运算结果会自动提升为int。

unsigned char a = 66;

if ((-a) < 0) printf("negative\n");
else printf("positive\n");

上面示例中,变量a是 unsigned char 类型,这个类型不可能小于0,但是-a不是 unsigned char 类型,会自动转为 int 类型,导致上面的代码输出 negative。

再看下面的例子。

unsigned char a = 1;
unsigned char b = 255;
unsigned char c = 255;

if ((a - 5) < 0) do_something();
if ((b + c) > 300) do_something();

上面示例中,表达式a - 5和b + c都会自动转为 int 类型,所以函数do_something()会执行两次。

4,函数

函数的参数和返回值,会自动转成函数定义里指定的类型。

int dostuff(int, unsigned char);

char m = 42;
unsigned short n = 43;
long long int c = dostuff(m, n);

上面示例中,参数变量m和n不管原来的类型是什么,都会转成函数dostuff()定义的参数类型。

下面是返回值自动转换类型的例子。

char func(void) {
  int a = 42;
  return a;
}

上面示例中,函数内部的变量a是int类型,但是返回的值是char类型,因为函数定义中返回的是这个类型。

二,强制类型转换

最佳实践是,我们在编写代码时,应该避免自动类型转换,因为自动类型转换可能导致出现意料之外的情况。

代码的行为始终在程序员的预料之中,是程序员必须追求的目标。

对于必不可少的类型转换,最好是使用强制类型转换

强制类型转换是指在一个值或变量的前面,使用圆括号指定类型(type),称之为casting。

(unsigned char) ch

上面示例将变量ch转成无符号的字符类型。

char c = (char)266;

上面示例中,(char)将266强制转换为char类型。

首先,虽然从语法上看,这种转换是没有必要的,因为对于赋值运算来说,编译器会把右边的值自动转换为左边的类型。但是,这样的代码是我们推荐的写法,更直观,便于阅读。

其次,把整型266强制转换为char类型,会出现数据截断,导致部分数据丢失,但由于这是我们意料之中的情况,就不会出现安全问题。

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

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

相关文章

探秘企业成功的秘密武器:这个知识库搭建攻略你必须知道

在数字化浪潮中,你的企业还在用传统的信息管理方式吗?别落后了!最新的企业知识库搭建攻略来了,它将是你提升企业竞争力、创新能力和员工效率的强力工具。让我们一起探索如何构建自己的知识王国,解锁企业成功的秘诀! 一、为什么你的企业需要立刻行动搭建知识库? 信息孤…

开启数字新纪元:全球首款开源AI女友,你的私人数字伴侣

在这个数字化飞速发展的时代,人工智能已经不再是科幻小说中的幻想,而是实实在在走进了我们的生活。今天,我们要介绍的,不仅仅是一项技术革新,更是一场关于陪伴的革命——全球首款开源AI女友,DUIX,已经横空出世! 🚀 革命性的开源平台 DUIX,由硅基智能精心打造,不…

INVS利用gatearray实现post-mask的function ECO

随着现代IC的设计发展&#xff0c;设计的规模和复杂度逐步增加&#xff0c;对于验证完备性的挑战越来越大&#xff0c;加之TO的时间压力&#xff0c;芯片设计通常会出现下列的场景&#xff1a; 芯片回片一次点亮大部分的case都可以顺利通过小部分的功能需要修正 对于重要的特…

全局唯一ID生成

全局ID生成器&#xff0c;是一种在分布式系统下用来生成全局唯一ID的工具需满足以下特性&#xff1a; 唯一性、递增性、安全性、高可用、高性能 生成在所有库或表中都满足唯一得ID 实现&#xff1a; 利用Redis的自增功能 INCRBY key increment (INCRBY | Docs)&#xff0c;并在…

网格布局之跨行越列

网格布局之跨行越列 欢迎关注&#xff1a;xssy5431 小拾岁月 参考链接&#xff1a;https://mp.weixin.qq.com/s/xStfSmewncTW49N0Y_Vhow 点击查看 使用场景 在常见的页面布局中&#xff0c;我们往往会遇到那种类似合并单元格的布局。比如&#xff1a;成绩排名、产品排名等等…

经典游戏案例:愤怒的小鸟

学习目标&#xff1a;愤怒的小鸟核心玩法 游戏画面 项目结构目录 部分核心代码 using System.Collections; using System.Collections.Generic; using birds; using utils; using UnityEngine;public class GameManager : MonoBehaviour {public static GameManager sInstanc…

每日待办事项提醒用什么便签app比较好?

在快节奏的现代生活中&#xff0c;我们经常需要记住各种事项&#xff0c;如会议、预约、购物清单等。这时&#xff0c;一个高效的便签App就显得尤为重要&#xff0c;可以帮助我们有效地管理日常任务和待办事项。而每日待办事项提醒用什么便签app比较好&#xff1f;面对市场上众…

vue中的状态管理

第1部分&#xff1a;引言 状态管理是应用中数据流动和变更的核心机制。在Vue应用中&#xff0c;状态管理不仅涉及到组件间的数据共享&#xff0c;还包括了数据的持久化、异步操作的处理等复杂场景。良好的状态管理策略可以提高应用的响应速度&#xff0c;降低组件间的耦合度&a…

交互式知识库问答:一种结合大型语言模型的多轮交互方法

在当今信息爆炸的时代&#xff0c;人们每天都要处理海量的数据和信息。在这样的背景下&#xff0c;基于知识库的问答系统&#xff08;KBQA&#xff09;成为了一个重要的研究领域&#xff0c;它旨在使计算机能够理解自然语言提出的问题&#xff0c;并从结构化的知识库中检索出准…

通信系统网络架构_1.局域网网络架构

当今&#xff0c;通信网络从大的方面主要包括局域网、广域网、移动通信网等网络形式。不同的网络会采用不同的技术进行网络构建。以下针对不同的网络给出各自的网络架构以及所采用的技术。 1.概述 局域网&#xff0c;即计算机局部区域网络&#xff0c;是一种为单一机构所拥有的…

四边形不等式优化

四边形不等式优化 应用于类似以下dp转移方程。 f i min ⁡ 1 ≤ j ≤ i ( w i , j , f i ) f_{i}\min_{1\le j\le i}(w_{i,j},f_{i}) fi​1≤j≤imin​(wi,j​,fi​) 假设 w i , j w_{i,j} wi,j​ 可以在 O ( 1 ) O(1) O(1) 的时间内进行计算。 在正常情况下&#xff0c;…

如何验证Rust中的字符串变量在超出作用域时自动释放内存?

讲动人的故事,写懂人的代码 在公司内部的Rust培训课上,讲师贾克强比较了 Rust、Java 和 C++ 三种编程语言在变量越过作用域时自动释放堆内存的不同特性。 Rust 通过所有权系统和借用检查,实现了内存安全和自动管理,从而避免了大部分内存泄漏。Rust 自动管理标准库中数据类…

本科生大厂算法岗实习经验复盘:从投递到面试的底层思维!

目录 投递渠道boss直聘官网邮箱内推 面试准备leetcode八股深挖项目自我介绍mock面试技巧答不出来怎么办coding反问 复盘技术交流群用通俗易懂方式讲解系列 节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面…

30 - 每位经理的下属员工数量(高频 SQL 50 题基础版)

30 - 每位经理的下属员工数量 -- 根据reports_to &#xff0c;获取employee_id,即分组用e1.reports_to&#xff0c;查询用e2.employee_id,e2.nameselect e2.employee_id,e2.name ,count(e1.reports_to) reports_count,round(avg(e1.age),0) average_age from Employees e1 left…

Springboot应用的信创适配-补充

Springboot应用的信创适配-CSDN博客 因为篇幅限制&#xff0c;这里补全Spring信创适配、数据库信创适配、Redis信创适配、消息队列信创适配等四个章节。 Springboot应用的信创适配 Springboot应用的信创适配&#xff0c;如上图所示需要适配的很多&#xff0c;从硬件、操作系统、…

【Linux基础IO】深入理解缓冲区

缓冲区在文件操作的过程中是比较重要的&#xff0c;理解缓冲区向文件刷新内容的原理可以更好的帮助我们更深层的理解操作系统内核对文件的操作。 FILE 因为IO相关函数与系统调用接口对应&#xff0c;并且库函数封装系统调用&#xff0c;所以本质上&#xff0c;访问文件都是通过…

国内外大模型生态发展报告!

很多同学只知类似Check GPT或者说对国内的一些比较了解&#xff0c;对国外的不太了解&#xff0c;所以在这总结。 1 大模型的发展 左表 名称参数特点发布时间GPT-215亿英文底模&#xff0c;开源2019年Google T5110亿多任务微调, 开源2019年GPT-3.51750亿人工反馈微调2022年M…

Django 循环模板标签

1&#xff0c;循环模板标签 Django 模板系统中提供了多种循环模板标签来迭代数据并显示列表、字典或其他可迭代对象。 1.2 {% for %} 标签 用于迭代列表或可迭代对象&#xff0c;并为每个元素提供上下文变量。 {% for item in items %}{{ item }} <!-- 渲染当前迭代项 -…

第二次IAG

IAG in NanJing City 我与南京奥体的初次相遇&#xff0c;也可能是最后一次&#xff01; 对我来说,IAG 演唱会圆满结束啦! 做了两场充满爱[em]e400624[/em]的美梦 3.30号合肥站&#xff0c;6.21号南京站[em]e400947[/em] 其实&#xff0c;没想到昨天回去看呀!(lack of money […

docker简单快速使用上手

1.Docker是什么&#xff1f; Docker 是一个开源的容器化平台&#xff0c;主要用于开发、运输和运行应用程序。它通过提供轻量级的虚拟化机制&#xff0c;使得开发者可以在一个隔离的环境中运行和管理应用程序及其依赖项。Docker 的核心组件包括镜像&#xff08;Image&#xff…