【C语言】强制类型转换的原理

简介: 【C语言】强制类型转换的原理

网络异常,图片无法展示
|


一、对指针进行强制类型转换

1.1printf打印时的转换形式

int main()
{
  int a = 5;
  printf("%lf", a);
  return 0;
}


解释代码:

这样的代码虽然能编译的过去,但其实是有不妥当的地方的,但平常我们在做题的时候难免遇到这样的代码风格,所以我们在这里解释一下这样的代码,但希望大家还是不要写出这样的代码来,这样的代码风格其实是不好的


其实我们先创建了一个大小为5的一个整型变量,并且这个变量以二进制的形式存储到栈区里面,占据了32个比特位,然后我们就进行打印了,但我们却以双精度浮点数的形式打印这个整型数字5,此时5的二进制代码已经存储到内存里面了,是没有进行改变的,所以存储形式是不会变得,而我们现在却改变了读取方式,我们用双精度的形式来读取这个二进制代码,分别读取他的符号位,指数位,有效位,所以我们打印出来的数,其实就是用读取浮点型的方法来读出整型5的二进制代码,然后进行结果的打印(如果这里不清楚浮点型的读取方法的话,可以去看我之前的博客,整形的存储)


1.2用指针操作符的转换形式

int a = 1234567890;
float *f = (float *)&a;
printf("%f", *f);


代码解释:

这样的代码风格是值得表扬的,我们都应该写出这样高质量的代码。


先把整型数字a的二进制代码放到内存里面,然后我们现在拿出这个整型变量a的地址,并将其进行修改为单精度浮点数的地址形式,然后我们把这个修改后的地址放到浮点型指针变量f里面去,最后我们对变量f进行解引用操作,其实就是将a的二进制代码按照浮点型的形式拿出来,然后进行打印,如果你想要知道这个打印的结果的话,你必须写出来他的二进制代码,然后将其按照浮点型中表示方法的对应比特位的个数拿出来,最后进行结果读取


1.3总结


这两种代码其实表达的内涵意思是相同的,他们是没有改变内存中变量的存储形式的,改变的是其读取方式,而且第二段的代码风格大家要学习,尽量写出这样的代码来。


这时有人可能会问到了,那既然两段代码表达的意思相同而且第二段代码的风格还比较好,那博主你还介绍第一段代码干什么呀,直接给我们讲哪个最好的代码不就得了吗???而且还列举个代码风格不好的代码,你这是何必呢?


其实答案很简单嘛,你做题总会遇到形形色色的代码,我不得给你介绍全面?要不然你肯定会想,那个笨笨的博主没有讲清楚这个知识点呀!不能你做不出来题,或者因为代码风格不好,你就不做这题了吧🤣🤣🤣


二、对变量进行强制类型转换

2.1 我们可能见到的形式

int main() {
    float a;
    scanf("%f", &a);
    if (a > 0)
    {
        int b = a + 0.5;
        printf("%d", b);     //这其实是牛客网上的一道题,我当时就没看懂这段代码
    }
    else
    {
        int b = a - 0.5;
        printf("%d", b);
    }
    return 0;
}

4a59929b2c6a47768138147ee0dad62f.png

代码解释:

其实这里的代码如果你看不懂的话,不怨人家的代码,还得怨你自己的能力不够,能看懂的人自然能看懂,你能力不够怨不得谁,这话也是说给我自己的哈


比较隐藏的地方就是,把那个浮点数+0.5赋值给了整型变量b里面了,这其实就是进行 了一个比较隐含的对变量进行的强制类型转换


比如你输入14.99,+0.5后变为15.49,这时我们又将其存到整型变量b里面,也就发生了强制类型转换,我们会改变a原来在内存里面表达为14.99的浮点型二进制代码形式,将其改变为表达15的整型二进制代码形式


2.2 标准形式

int main()
{
  int a = 1234567890;
  float f = (float)a;
  printf("%lf", f);
}


int main()
{
  int a = 1234567890;
  double f = (double)a;
  printf("%lf", f);
}


代码解释:

编译器会先把a按照整型的形式(1234567890)将它的二进制代码存到栈区里面,然后我们要将其存到浮点型变量f里面,所以这时就又按照浮点型的格式存到内存里面了(表达的为1234567890.000000),但此时它在内存中的存储方式已经改变了,他变成能表达为1234567890.000000这样的浮点型数字的二进制代码了,而不是原来表达为1234567890 这样的整型数字的二进制代码了,所以我们打印结果就变成了1234567890.000000


这里给大家放了两端代码,其实还想另外对比一下单精度浮点型和双精度浮点型的区别,我们把1234567890这么大的整型数字存到内存后,将其强制类型转换为浮点型然后打印,其实就变成了原有的数字后面带上小数位,但因为精度的不同,所以我们两种浮点型能够表达的最大精度数字也是不同的,如果你这里编译一下第一段代码,就会发现它和第二段代码的结果不一样,这其实就是他的精度不够无法打印出你所期望的数字。我们只要将类型改成double就行了


2.3总结

变量的强制类型转换和指针的强制类型转换,本质就在于一个改变了其内存二进制的存储形式,一个未改变其内存二进制的存储形式













































相关文章
|
6月前
|
存储 程序员 C语言
C语言强制类型转换运算符
C语言强制类型转换运算符
39 1
|
6月前
|
存储 C语言
C语言强制类型转换
C语言强制类型转换
59 0
|
6月前
|
C语言
【C语言】大小写字母的相互转化:多种方法解析及原理说明
【C语言】大小写字母的相互转化:多种方法解析及原理说明
459 0
|
6月前
|
C语言
C语言malloc与free实现原理
malloc()的实现很简单。它首先会扫描之前由 free()所释放的空闲内存块列表,以求找到尺寸大于或等于要求的一块空闲内存。(取决于具体实现,采用的扫描策略会有所不同。例如,first-fit 或 best-fito。)如果这一内存块的尺寸正好与要求相当,就把它直接返回给调用者。如果是一块较大的内存,那么将对其进行分割,在将一块大小相当的内存返回给调用者的同时,把较小的那块空闲内存块保留在空闲列表中。 如果在空闲内存列表中根本找不到足够大的空闲内存块,那么 malloc()会调用 sbrk()以分配更多
50 0
C语言malloc与free实现原理
|
存储 编译器 C语言
27 C语言 - 强制类型转换
27 C语言 - 强制类型转换
50 0
|
1月前
|
自然语言处理 编译器 Linux
C语言中抽象的编译和链接原理
C语言中抽象的编译和链接原理
20 1
|
3月前
|
存储 NoSQL Java
线程池的原理与C语言实现
【8月更文挑战第22天】线程池是一种多线程处理框架,通过复用预创建的线程来高效地处理大量短暂或临时任务,提升程序性能。它主要包括三部分:线程管理器、工作队列和线程。线程管理器负责创建与管理线程;工作队列存储待处理任务;线程则执行任务。当提交新任务时,线程管理器将其加入队列,并由空闲线程处理。使用线程池能减少线程创建与销毁的开销,提高响应速度,并能有效控制并发线程数量,避免资源竞争。这里还提供了一个简单的 C 语言实现示例。
|
5月前
|
存储 算法 C语言
二分查找算法的概念、原理、效率以及使用C语言循环和数组的简单实现
二分查找算法的概念、原理、效率以及使用C语言循环和数组的简单实现
|
5月前
|
算法 搜索推荐 C语言
深入了解C语言的qsort函数:原理及相关知识
深入了解C语言的qsort函数:原理及相关知识
76 1
|
5月前
|
缓存 C语言
glibc函数malloc的工作原理
glibc函数malloc的工作原理
42 0