【C语言】深入理解数据类型转换与运算

文章目录

  • 1.数据类型转换
      • 在分析源程序之前,我们需要了解几个基本概念:
      • 现在来分析源程序中的变量及其对应的十进制真值以及扩展操作方式:
    • 1.1. `short si = -32768;`
    • 1.2. `unsigned short usi = si;`
    • 1.3. `int i = si;`
    • 1.4. `unsigned ui = usi;`
  • 2.编写程序说明不同数据类型之间进行转换时在表数范围和精度上的变化。
    • 2.1. 给定一个`short`型数据 `-12345`,分别转换为`int、unsigned short、unsigned int、float`类型的数据;
    • 2.2. 给定一个`int`型数据`2147483647`,分别转换为`short、unsigned short、unsigned int、float、double`类型的数据;
    • 2.3.给定一个`float`型数据`123456.789e5`,转换成`int、double`型数据;
    • 2.4.给定一个`double`型数据`123456.789e5`,转换成`int、float`型数据。`#include <stdio.h>`
    • 根据实验结果,回答下列问题:
      • (1)补码整数(如`int`型数)是否总能转换为等值的`float`类型数据?为什么?
      • (2)`float`型数据是否总能转换成等值的`double`型数据?为什么?
      • (3)长数被截断成短数后可能发生什么现象?为什么?
  • 3.编程计算下列表达式的值:
    • 3.1. unsigned int型数据: 1+4294967295=?;1-4294967295=?
    • 3.2. int型数据:2147483647+1=?;-2147483648-1=?

在程序设计中,数据类型转换和运算溢出是一个常见但也容易被忽视的问题。本文通过具体的代码示例,深入分析了不同数据类型之间的转换及在运算过程中可能出现的溢出现象,旨在帮助读者更加深入地理解这些概念。

1.数据类型转换

让我们首先来分析,下列源程序中的变量在机器内是如何表示的,以及各变量对应的十进制真值是多少,无符号数和带符号整数的扩展操作方式是否相同?各是如何进行的?

#include <stdio.h>
int main()
{short si = -32768;unsigned short usi = si;int i = si;unsigned ui = usi;printf("%d\n", si);printf("%u\n", usi);printf("%d\n", i);printf("%u\n", ui);return 0;
}

在这里插入图片描述

在分析源程序之前,我们需要了解几个基本概念:

  1. 有符号整数:以补码形式存储,最高位为符号位,0表示正数,1表示负数。
  2. 无符号整数:以二进制形式存储,没有符号位,全部位都用于表示数值。

现在来分析源程序中的变量及其对应的十进制真值以及扩展操作方式:

在这里插入图片描述

1.1. short si = -32768;

在这里插入图片描述
si 是一个有符号短整型变量,占用2个字节(16位)。
十进制真值-32768
扩展操作方式:将-32768直接存储到 si 中,不需要进行扩展操作。

1.2. unsigned short usi = si;

在这里插入图片描述

usi 是一个无符号短整型变量,占用2个字节(16位)。
十进制真值32768
扩展操作方式:将 si 的二进制补码表示直接转换为无符号数的二进制表示。

1.3. int i = si;

在这里插入图片描述

i 是一个有符号整型变量,占用4个字节(32位)。
十进制真值-32768
扩展操作方式:由于 si 是一个有符号短整型变量,它的扩展操作是将其符号位扩展到更高位,即复制符号位,直到填满 i 的所有位。

1.4. unsigned ui = usi;

在这里插入图片描述

ui 是一个无符号整型变量,占用4个字节(32位)。
十进制真值32768
扩展操作方式:将 usi 的二进制表示直接转换为无符号整数的二进制表示。
综上所述,无符号数和带符号整数的扩展操作方式是不同的。无符号数直接将二进制表示转换为目标类型,而带符号整数需要进行符号位的扩展操作。

2.编写程序说明不同数据类型之间进行转换时在表数范围和精度上的变化。

2.1. 给定一个short型数据 -12345,分别转换为int、unsigned short、unsigned int、float类型的数据;

#include <stdio.h>
int main() {short s = -12345;int i = s;printf("s as int: %d\n", i);unsigned short us = (unsigned short)s;printf("s as unsigned short: %u\n", us);unsigned int ui = (unsigned int)s;printf("s as unsigned int: %u\n", ui);float f = (float)s;printf("s as float: %f\n", f);return 0;
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

由于short类型是有符号的,而unsigned shortunsigned int都是无符号的,因此s转换为unsigned shortunsigned int时会被解释为一个很大的正整数

在进行float类型的转换时,系统会将short类型的值转换为float类型的值,并在其末尾添加一些额外的零,以使其符合float类型的规格化格式。

2.2. 给定一个int型数据2147483647,分别转换为short、unsigned short、unsigned int、float、double类型的数据;

#include <stdio.h>
int main() {int i = 2147483647;short s = (short)i;printf("i as short: %d\n", s);unsigned short us = (unsigned short)i;printf("i as unsigned short: %u\n", us);unsigned int ui = (unsigned int)i;printf("i as unsigned int: %u\n", ui);float f = (float)i;printf("i as float: %f\n", f);double d = (double)i;printf("i as double: %lf\n", d);return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在32位系统中,int类型占据4个字节,范围为-21474836482147483647
当将最大值2147483647转换为short类型时,超出了short类型的范围,导致截断,结果为-1
当将最大值2147483647转换为unsigned short类型时,超出了unsigned short类型的范围,结果为65535
当将最大值2147483647转换为unsigned int类型时,结果仍然是2147483647,因为unsigned int类型足够存储这个数值。
当将最大值2147483647转换为float类型时,由于float类型的精度限制,整数部分超过了可表示的范围,结果变为2147483648.000000
当将最大值2147483647转换为double类型时,double类型的精度比float更高,能够保持原始值。

2.3.给定一个float型数据123456.789e5,转换成int、double型数据;

#include <stdio.h>
int main() {float f = 123456.789e5;int i = (int)f;printf("f as int: %d\n", i);double d = (double)f;printf("f as double: %lf\n", d);return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在32位机器上,int类型占据4个字节,范围为-21474836482147483647。而变量f的值为123456.789e5,即123456.789乘以105次方,结果为12345678900
当将float类型的变量f转换为int类型时,会发生截断操作。由于整数部分超过了int类型的范围,截断结果为-2147483648,即int类型的最小值。
当将float类型的变量f转换为double类型时,由于double类型的精度比float更高,能够准确表示变量f的值。因此,结果为12345679104.000000

2.4.给定一个double型数据123456.789e5,转换成int、float型数据。#include <stdio.h>

int main() {double d = 123456.789e5;int i = (int)d;printf("d as int: %d\n", i);float f = (float)d;printf("d as float: %f\n", f);return 0;
}

在这里插入图片描述
在这里插入图片描述
在32位机器上,int类型占据4个字节,范围为-21474836482147483647。而变量d的值为123456.789e5,即123456.789乘以105次方,结果为12345678900
当将double类型的变量d转换为int类型时,会发生截断操作。由于整数部分超过了int类型的范围,截断结果为2147483647,即int类型的最大值。
当将double类型的变量d转换为float类型时,由于float类型的精度较低,无法完全保留double类型的精度。因此,结果为12345679232.000000,存在舍入误差。

根据实验结果,回答下列问题:

(1)补码整数(如int型数)是否总能转换为等值的float类型数据?为什么?

补码整数(如int型数)并不总能转换为等值的float类型数据。这是因为在转换过程中,如果整数部分过大或者过小,超出了float类型能表示的范围,就会发生精度丢失或者溢出的情况。例如,在32位机器上,int类型范围为-21474836482147483647,而float类型的有效范围约为±3.4e±38,当int型数据超出了这个范围时,就无法准确表示为对应的float类型数据。

(2)float型数据是否总能转换成等值的double型数据?为什么?

float型数据并不总能转换成等值的double型数据。虽然float和double都表示浮点数,但是double类型具有更高的精度和表示范围。因此,当一个float类型数据转换为double类型时,会出现精度损失的情况,因为double类型无法准确表示所有的float类型数据,特别是对于较大或较小的浮点数。

(3)长数被截断成短数后可能发生什么现象?为什么?

将长数截断为短数后,可能发生精度丢失或溢出的现象。例如,将一个较大的double类型数据截断为float类型,或者将一个int类型数据赋给short类型变量,都可能导致数据溢出或者精度丢失。这是因为短数类型能够表示的范围和精度比长数类型更小,所以超出范围的部分会被截断或者舍入,导致数据的改变。

3.编程计算下列表达式的值:

3.1. unsigned int型数据: 1+4294967295=?;1-4294967295=?

#include <stdio.h>int main() {unsigned int x = 1;unsigned int y = 4294967295;// 1 + 4294967295unsigned int sum = x + y;printf("1 + 4294967295 = %u (0x%x)\n", sum, sum);// 1 - 4294967295unsigned int diff = x - y;printf("1 - 4294967295 = %u (0x%x)\n", diff, diff);return 0;
}

在这里插入图片描述

  • 对于第一个表达式,unsigned int类型的数据是无符号数,范围为04294967295。由于1加上4294967295等于4294967296,超出了unsigned int类型的表示范围,因此结果为0。对于无符号数来说,溢出后会自动回绕,即4294967296等于0
  • 对于第二个表达式,1减去4294967295的结果为2。同样地,由于unsigned int类型是循环的,4294967295减去1实际上等于2。

3.2. int型数据:2147483647+1=?;-2147483648-1=?

#include <stdio.h>int main() {int a = 2147483647;int b = 1;int c = -2147483648;int d = -1;// 2147483647 + 1int sum = a + b;printf("2147483647 + 1 = %d (0x%x)\n", sum, sum);// -2147483648 - 1int diff = c - d;printf("-2147483648 - 1 = %d (0x%x)\n", diff, diff);return 0;
}

在这里插入图片描述

  • 对于第一个表达式,int类型的数据是有符号数,范围为-21474836482147483647。由于2147483647加上1等于2147483648,超出了int类型的表示范围,因此结果为-2147483648。这是因为在有符号整数中,溢出会导致“环绕”现象。
  • 对于第二个表达式,-2147483648减去1的结果为2147483647。由于-1的补码为0xffffffff,将-2147483648减去1相当于对-2147483648取反后加1,得到的就是2147483647

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TIME_WAIT状态套接字重新使用

《TIME_WAIT相关知识》里边有相关理论知识。 《TIME_WAIT状态TCP连接导致套接字无法重用实验》有相关实验。 现代Linux的TCP协议栈已经做了许多升级&#xff0c;所以可以让我们直接重用TIME_WAIT状态套接字而不会引起问题。下边是优化的内容&#xff1a; 1.新连接的SYN告知序列…

在Spring Boot中隔离@Async异步任务的线程池

在异步任务执行的时候&#xff0c;我们知道其背后都有一个线程池来执行任务&#xff0c;但是为了控制异步任务的并发不影响到应用的正常运作&#xff0c;我们需要对线程池做好相关的配置&#xff0c;以防资源过度使用。这个时候我们就考虑将线程池进行隔离了。 那么我们为啥要…

C语言生成随机数的方法

文章目录 一、rand函数&#xff1a;二、srand函数&#xff1a;三、time函数&#xff1a;四、生成范围随机数公式&#xff1a;五、实战练习&#xff1a;总结 一、rand函数&#xff1a; int rand( void ); 我们先来看一下rand函数的基本信息&#xff1a; rand函数根据种子生成随…

C++相关闲碎记录(1)

1、C绘制爱心图像 #include <iostream> #include <cmath>using namespace std;int main() {// 心形曲线公式 (x^2 y^2 - a)^3 - x^2*y^3 0double a 1;double bound 1.5 * sqrt(a);double step 0.05;for (double y bound; y > -bound; y - step) {for (do…

【面试题】JavaScript高级循环方法

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 除了for循环♻️&#xff0c;for-of,for-each循环♻️也是一个不错的选择 先说for-of循环♻️ 认识for-of循环♻️…

进程等待讲解

今日为大家分享有关进程等待的知识&#xff01;希望读完本文&#xff0c;大家能有一定的收获&#xff01; 正文开始&#xff01; 进程等待的引进 既然我们今天要讲进程等待这个概念&#xff01;那么只有我们把下面这三个方面搞明白&#xff0c;才能真正的了解进程等待&#x…

基于OpenCV+YOLOv5实现车辆跟踪与计数(附源码)

导 读 本文主要介绍基于OpenCVYOLOv5实现车辆跟踪与计数的应用&#xff0c;并给出源码。 资源下载 基础代码和视频下载地址&#xff1a; https://github.com/freedomwebtech/win11vehiclecount main.py代码:​​​​​​​ import cv2import torchimport numpy as npfrom tr…

spring Cloud在代码中如何应用,erueka 客户端配置 和 服务端配置,Feign 和 Hystrix做高可用配置

文章目录 Eureka一、erueka 客户端配置二、eureka 服务端配置 三、高可用配置FeignHystrix 通过这篇文章来看看spring Cloud在代码中的具体应用&#xff0c;以及配置和注解&#xff1b; Eureka 一、erueka 客户端配置 1、Eureka 启禁用 eureka.client.enabledtrue 2、Eurek…

Android修行手册-ViewPager定制页面切换以及实现原理剖析

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

基于Springboot的墙绘产品展示交易平台(有报告),Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的墙绘产品展示交易平台&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff0…

基于DSP/SOC音乐灯效系统设计方法

音乐灯效系统设计方法 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, 三种方法: (1)MIC 采集音乐信号变化,(2)直接获取SPK 模拟音频…

20231127让RK3399的挖掘机开发板在Andorid12系统下休眠唤醒之后禁止锁屏

20231127让RK3399的挖掘机开发板在Andorid12系统下休眠唤醒之后禁止锁屏 2023/11/27 20:55 适用于SOC以及系统版本&#xff1a; RK3399&#xff1a;Android10/11/12 RK3568&#xff1a;Android11/12 RK3588&#xff1a;Android12 当RK3399平台的Android12系统在休眠之后&#x…