C语言KR圣经笔记 2.7类型转换

news2024/9/30 3:31:35

2.7 类型转换

当一个操作符有几个不同类型的操作数时,会根据少量规则将几个操作数转换为一个公共的类型。

通常来说,仅有的自动转换,是在不丢失信息的情况下将“窄”的操作数转换为“宽”的类型,例如在 表达式 f + i 中将整数转换成浮点数。无意义的表达式,如用 float 做数组下标,是不允许的。可能丢失信息的表达式,如将一个较长的整数赋给较短的,或把浮点类型赋值给整数,可能会引起警告,但并非不合法。

char 就是小整数,因此 char 可以自由地用在算术表达式中。这为某些类型的字符转换带来相当可观的灵活性。例如下面这个简单实现的函数 atoi, 将数字字符串转换成对应的数值:

/* atoi: 把s转换成整数 */
int atoi(char s[])
{
    int i,n;

    n = 0;
    for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
        n = 10 * n + (s[i] - '0');
    return n;
}

如我们在第一章讨论的,表达式

    s[i] - '0'

会得到s[i]中字符对应的数值,因为'0','1',...到 '9'的值是递增的。

另一个 char  到 int 转换的例子是函数 lower,能把ASCII字符集的单个字符转换成小写。如果该字符不是大写的,lower 将其原样返回。

/* lower: 把c转换成小写;仅用于ASCII码 */
int lower(int c)
{
    if (c >= 'A' && c <= 'Z')
        return c + 'a' - 'A';
    else
        return c;
}

这对ASCII编码是有效的,因为对应的大写和小写字母的数值之间有一个固定的差值,而且大小写字母表都是连续的——在A和Z之间只有字母。然而,第二个规则对EBCDIC字符集无效,因此如果用到EBCDIC字符集上,这个代码不只会转换字母。

标准库头文件 <ctype.h>(具体描述见附录B)中,定义了一系列不依赖于字符集的测试和转换函数。例如,函数 tolower 是可移植的,可替代上面写的 lower 函数。类似的,

    c >= '0' && c <= '9'

上面这个测试可以替换为:

    isdigit(c)

从现在开始我们都将用 <ctpye.h> 中的函数。

字符到整数的转换有个微妙之处。语言没有指定 char 类型的变量是有符号还是无符号值。当 char 被转换为 int 时,可能会得到负整数吗?答案随机器的不同而不同,反映了架构之间的差异。在某些机器上,最左端 bit 位为1的char 会被转换为负数(即“符号位扩展”)。而在另外的机器上,char 提升为 int 是通过在左端加 0 来做的,这样就总是正数。

C的定义保证,机器的标准打印字符集中的所有字符永不为负,因此这些字符在表达式中也总是为正值。但在字符变量中储存的任意位模式,可能在某些机器上看起来是负的,而在其他机器上是正的。为了可移植性,如果要在char 变量中保存非字符数据,总是指定 signed 或 unsigned。

关系表达式如 i > j,以及通过 && 和 || 连接起来的逻辑表达式,如果为真则值为1,为假则值为0。这样的话,下面的赋值:

    d = c >= '0' && c <= '9'

如果c为数字则d的值被设为1,否则为0。然而,如 isdigt 这样的函数可能返回任意非0值来表示真。在 if、while 和 for 等的测试部分中,“真”即意味着“非0”,所以不会有区别。

隐式的算术转换,也大多如程序员的预期。通常来说,对有两个操作数的操作符(二元操作符)如 + 和 *,如果操作数的类型不一样,则在操作之前,“低”的类型会被提升为“高”的类型。结果得到高的类型。附录A的第6节精确描述了这些规则。然而,如果没有 unsigned 类型的话,下面这几条不太正式的规则就够用了:

若其中一个操作数为 long double,则把另一个也转换为long double。

否则,若其中一个操作数为 double,则把另一个也转换为 double。

否则,若其中一个操作数为 float,则把另一个也转换为 float。

否则,把 char 和 short 转换为 int。

然后,若其中一个操作数为 long,则把另一个也转换为 long。

注意,表达式中的 float 不会自动转换成double;这里对语言最初的定义做了修改。通常来说,像 <math.h> 中的算术函数会使用双精度。使用 float 的主要原因,是为了节省大数组的存储空间,稍微次要的原因,是为了在双精度计算特别“昂贵”的机器上节省时间。

当涉及 unsigned 操作数时转换规则更加复杂。问题在于有符号和无符号值的比较是依赖于机器的,因为它们依赖于不同整数类型的长度。例如,假设 int 是 16 位而 long 是 32 位。则 -1L < 1U,因为 1U 是 int ,提升为 signed long。但 -1L > -1UL,因为 -1L被提升为 unsigned long,看起来像是个非常大的正数。

转换也伴随着赋值发生,右侧的值被转换成左侧值的类型,即是赋值表达式的结果类型。

字符被转换为整数,可能是符号扩展也可能不是,如前所述。

通过丢弃高位,较长整数被转换成较短的整数或char。因此经过如下赋值

int i;
char c;

i = c;
c = i;

c 的值保持不变。不管是否涉及符号扩展,都是如此。然而,调换赋值顺序可能会丢失信息。

如果 x 是 float 而 i 是 int,则 x = i 和 i = x 都会引起转换;float 到 int 会截断所有小数部分。当 double 转换为 float, 值是四舍五入还是截断,依赖于实现。

由于函数调用的参数也是表达式,当参数传给函数时也会发生转换。在缺少函数原型时,char 和 short 成为 int,float 成为 double。这就解释了为什么我们在声明函数实参时用 int 和 double,即使调用函数时传入的值是 char 和 float。

最后一提,可以使用一元操作符(称为 cast),在任意表达式中进行强制的类型转换。如下结构

(类型名) 表达式

上面的表达式被转换为括号中的类型(通过前述的转换规则)。cast 的精确含义,就像是将表达式赋值给指定类型的变量,然后把这个变量代替整个结构来使用。例如,库函数 sqrt 期望接受一个 double 参数,如果不小心传入了其他类型则会产生垃圾结果。(sqrt 在 <math.h> 中声明)因此,如果 n 是整数,我们要使用

    sqrt((double) n)

在将其传入sqrt之前,把 n 的值转换成 double。注意,cast 转换生成的是 n 的合适类型,n本身不会被改变。cast 操作符和其他一元操作符有相同的优先级,参见本章末尾总结的操作符优先级表。

如果函数原型有声明参数(正常来说都应当如此),则当函数调用时,该声明可以造成所有参数的强制类型转换。这样,给出 sqrt 的函数原型:

    double sqrt(double);

对它的调用

root2 = sqrt(2);

会强制将整数 2 转换为 double 值 2.0,不需要进行任何 cast 操作。

标准库包含了一个可移植的伪随机数生成器和一个初始化种子的函数;前者演示了cast的使用:

unsigned long int next = 1;

/* rand: 返回 0到32767之间的伪随机数 */
int rand(void)
{
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

/* srand: 为rand设置种子 */
void srand(unsigned int seed)
{
    next = seed;
}

练习 2-3,写个函数 htoi(s) 将十六进制字符串(包括可选的0x或0X),转换成对应的整数值。十六进制允许的数位是 0-9,a-z,A-Z。

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

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

相关文章

如何用.bat文件直接安装jar包

大家应该都知道一个maven引入jar包&#xff0c;如果直接把jar包放到目录&#xff0c;这样是没用的&#xff0c;引入还是会失败 这里我们可以创建一个.bat的windows系统文件&#xff0c;写入pom.xml对应的groupid&#xff0c;artifactId&#xff0c;version pom.xml中进入jar包…

深入理解数据结构(2)——用数组实现队列

数组是一种数据结构&#xff0c;队列也是一种数据结构。它们都是由基础的语法实现的。 如果一个数据结构可以用另外的数据结构来实现&#xff0c;那么可以有力的证明——“数据结构是一种思想”&#xff0c;是一种讲语法组合起来实现某种功能的手段 “整体大于局部” 一、队列的…

大模型相关概念

GGML 以纯C语言编写的框架&#xff0c;让用户可以在MacBook电脑上轻松运行大型语言模型&#xff0c;这种模型通常在本地运行成本较高。目前&#xff0c;这一框架主要被业余爱好者使用&#xff0c;但在企业模型部署方面也有广泛的应用前景。 量化快速入门 我们首先简单介绍一下…

原生JavaScript实现的SPA单页应用(hash路由)

什么叫做SPA单页应用 单页Web应用 &#xff08;single page web application&#xff0c;SPA&#xff09; &#xff0c;就是只有一张Web页面的应用&#xff0c;是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。 单页应用的说法是在JavaScript和AJA…

超写实数字人小灿加入,助力火山语音全类型虚拟数字人应用创新

当发现更多AI科技作用于日常生活时&#xff0c;你是否想过竟然有一天会与AI数字人做同事&#xff1f;日前&#xff0c;火山语音团队重磅推出了一位神秘新成员——首个超写实数字员工小灿&#xff01;这位新同事不仅形象清新美丽&#xff0c;还有着很强的亲和力&#xff0c;大幅…

ardupilot开发 --- CAN BUS、DroneCAN 、UAVCAN 篇

1. CAN BUS、DroneCAN 、UAVCAN 区别 UAVCAN是一种轻量级协议&#xff0c;旨在通过CAN BUS 在航空航天和机器人应用中实现可靠通信。 UAVCAN网络是分散的对等网络&#xff0c;其中每个对等体&#xff08;节点&#xff09;具有唯一的数字标识符 - 节点ID&#xff0c;并且仅需要…

minio + linux + docker + spring boot实现文件上传与下载

minio docker spring boot实现文件上传与下载 1.在linux上安装并启动docker2.在docker中拉取minio并启动3.Spring Boot 整合 minio4.测试 minio 文件上传、下载及图片预览等功能 1.在linux上安装并启动docker 检查linux内核&#xff0c;必须是3.10以上 uname ‐r安装docker…

没有电脑也不用担心,在Android设备上也可以轻松使用ppt

PowerPoint是制作幻灯片的好工具&#xff0c;无论是工作、学校还是个人使用。但有时你无法使用电脑或笔记本电脑&#xff0c;你必须在旅途中做演示。 这就是PowerPoint for Android派上用场的地方。它允许你在移动设备上创建、编辑和呈现幻灯片。以下是要遵循的步骤&#xff1…

[每周一更]-(第69期):特殊及面试的GIT问题解析

整合代码使用过程的问题&#xff0c;以及面试遇到的细节&#xff0c;汇总一些常用命令的对比解释和对比&#xff1b; 1、fetch和pull区别 git fetch是将远程主机的最新内容拉到本地&#xff0c;用户在检查了以后决定是否合并到工作本机分支中。 git pull则是将远程主机的最新内…

unity button移动位置some values driven by canvas

1 可以在button父节点把限制取消勾选 2 在不动整个布局的情况下&#xff0c;只修改局部变量&#xff1a;忽略布局即可

Instagram引流技巧:如何充分利用社交媒体来增加独立站流量

在数字时代&#xff0c;社交媒体已成为推广产品、服务和内容的重要工具之一。Instagram&#xff0c;作为其中之一&#xff0c;以其视觉化特点和庞大的用户基础&#xff0c;为独立站和个人品牌提供了难得的机会。本文Nox聚星将和大家探讨如何充分利用Instagram&#xff0c;将其作…

【从瀑布模式到水母模式】ChatGPT如何赋能软件研发全流程

文章目录 &#x1f384;前言&#x1f354;本书概要&#x1f33a;内容简介&#x1f33a;作者简介&#x1f33a;专家推荐&#x1f6f8;读者对象&#x1f354;彩蛋 &#x1f384;前言 计算机技术的发展和互联网的普及&#xff0c;使信息处理和传输变得更加高效&#xff0c;极大地…

2核4G服务器 如何设计编码一款扛得住高并发高吞吐量的商品秒杀系统

题目 最近要参加一个秒杀商品系统比赛 【题目】设计并演示一款商品秒杀系统 【要求】设计并实现程序&#xff0c;模拟该商品秒杀系统的基本功能包括但不限于&#xff1a; 1.商品管理&#xff1a;每个商品都有唯一的ID、名称、库存数量和秒杀价格。 2.用户管理&#xff1a;每个…

MyBatis 基础用法详解

目录 什么是MyBatis 前置工作 创建MyBatis项目 MyBatis的使用 1.查询 1.1全查询 1.2传参查询 2.删除 3.修改 4.添加 什么是MyBatis MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设…

使用Python实现一个简单的斗地主发牌

使用Python实现一个简单的斗地主发牌 1.源代码实现2.实现效果 1.源代码实现 import random# 定义扑克牌的花色和大小 suits [♠, ♥, ♣, ♦] ranks [2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A]# 初始化一副扑克牌 deck [suit rank for suit in suits for rank in ranks]# …

怎么用Python写一个浏览器集群框架

这是做什么用的 框架用途 在采集大量新闻网站时&#xff0c;不可避免的遇到动态加载的网站&#xff0c;这给配模版的人增加了很大难度。本来配静态网站只需要两个技能点&#xff1a;xpath和正则&#xff0c;如果是动态网站的还得抓包&#xff0c;遇到加密的还得js逆向。 所以…

ChatGPT如何赋能探究深度学习、神经网络与卷积神经网络

计算机技术的发展和互联网的普及&#xff0c;使信息处理和传输变得更加高效&#xff0c;极大地改变了金融、商业、教育、娱乐等领域的运作方式。数据分析、人工智能和云计算等新兴技术&#xff0c;也在不断地影响和改变着各个行业。 如今&#xff0c;我们正在见证人工智能技术…

【Overload游戏引擎细节分析】PBR材质Shader

PBR基于物理的渲染可以实现更加真实的效果&#xff0c;其Shader值得分析一下。但PBR需要较多的基础知识&#xff0c;不适合不会OpenGL的朋友。 一、PBR理论 PBR指基于物理的渲染&#xff0c;其理论较多&#xff0c;需要的基础知识也较多&#xff0c;我在这就不再写一遍了&#…

如何构造强一致性系统?理解数据一致性里的2PC和TCC模式原理,以及如何做(有图)

背景 首先&#xff0c;读这篇文章的时候你应该先了解什么是事务、什么是分布式事务。 我这里举2个例子&#xff0c;典型场景有两个&#xff1a; 1、一个应用有两个数据库&#xff0c;一个数据库是订单&#xff0c;另一个数据库是积分&#xff0c;要求下订单的时候同时给用户积…

el-table添加固定高度height后高度自适应

0 效果 1 添加自定义指令 新建目录src/directive/el-table 在el-table目录下新建文件adaptive.js import { addResizeListener, removeResizeListener } from element-ui/src/utils/resize-event// 设置表格高度const doResize async(el, binding, vnode) > {// 获取表格…