C语言自动类型转换:int型数据 + float数据 → double型?纠正教材中的错误用法!


目录

前言

一、官方标准证明(C89、C99、C11)

二、代码证明

三、一些教材上的错误的用法来源 与 K&R(非正式)标准

四、参考博文

五、C语言各个版本PDF下载


前言

笔者之前看到一些教材关于自动类型转换章节的知识点写到:1.float型数据参与运算时,先转换为double型数据再计算;2.float型数据 与 int型数据运算,先将两者转换为double型,再运算。与笔者的实操结果不符,于是经过充分的查阅后,发现上述知识点已经是30年前过时老掉牙的用法了。今天笔者通过官方标准、代码证明、错误来源 来充分证明。


一、官方标准证明(C89、C99、C11)

距今为止,C语言官方标准共发展了四代:C89、C99、C11、C17

C89、C99、C11这三代标准中均对于float + float → float 、 int + float → float 作出了明确说明。由于笔者暂未找到C17官方标准文档,再加之C17相较于C11未发生语法改动,因此本文暂不作C17标准的讨论。


1.C89

首先,C89是由美国国家标准协会(ANSI)在 1989年正式公布的标准,该标准定义了C语言和C标准库

p.s:

  • 国际标准化组织(ISO)采用了这套C标准,因此ISO CANSI C是完全相同的标准。

  • ANSI于1989年批准该标准,因此通常称之为C89

  • ISO于1990年批准该标准,因而又有C90的叫法。


C89标准中的6.2.1.5章节中有说明:float + float → float 、 int + float → float。如下:


由于我国的C标准采用的是此版本,所以相当于C89的官方中文翻译版。

2.C99

在后来1999年出台的C99标准中关于float + float →float、 int + float → 的规定并无变化。(翻译放在英文原文的下方)

3.C11

2011年出台的C11标准中6.3.1.8章节中自动类型转换的规定与C99标准的此部分规定完全一致:



综上,C89、C99、C11标准中对于float + float → float、 float + int → float 的说明都是一样的。

因此,自动类型转换规则应该是下图这样的:(C99标准的unsigned与long的混合情况暂不重要 不讨论- -)仅供参考欢迎补充


二、代码证明

编译器为DEV C++,采用标准为C99。

测试代码如下:


/*	编译器:DEV C++
	采用标准:C99 
*/

#include<stdio.h>

int main()
{
//	1. int + float →float   而不是 int + float →double   
	int int_a = 1; 		
	float float_a = 2.5;    
	
	printf("%f\n",int_a + float_a); //3.500000 
	printf("%d",sizeof(int_a + float_a)); //4
//	备注:第一个printf结果为3.500000说明int转为了实型,而非float转为了int。与争议点无关,仅供自己测试 。 
//		 第二个printf结果为4说明int转为了float(4字节),而非int和float都转为了double(8字节)


//	2.float + float →float   而不是 float + flaot →double 
	float float_b = 1.5;
	
	printf("%f\n",float_a + float_b); 	//4.000000
	printf("%d\n",sizeof(float_a + float_b));	//4
//	备注:第一个printf结果为4.000000,与本次话题无关,仅供自己测试 。 
//		 第二个printf结果为4说明int转为了float(4字节),而非int和float都转为了double(8字节)


//======================以下三点为补充测试========================


//	3. char + short → int   而不是 char + short →short 
	char char_a = 1 ; 
	short short_a = 1;
		
	printf("%d,%d\n",sizeof(char_a),sizeof(short_a)); // 1,2
	printf("%d\n",sizeof(char_a + short_a)); //4
//	备注:char 1字节 ,short 2字节 , 此例说明char + short 运算,都转为了int 


//	4. long + float → float   而不是 long + float →double 
	long long_a = 1; 
//	float_a在例1中已定义 
	
	printf("%f\n",long_a + float_a); //3.500000 
	printf("%d\n",sizeof(long_a + float_a)); //4
//	备注:第一个printf结果为3.500000说明long转为了实型,而非float转为了long 。与争议点无关,仅供自己测试 。  
//		 第二个printf结果为4说明long转为了float(4字节),而非long和float都转为了double(8字节)


//	5.double + float →double
	double double_a = 1.5;
	
	printf("%f\n",double_a + float_a);  //4.000000
	printf("%d\n",sizeof(double_a + float_a)); //8
//	备注:第一个printf结果为4.000000,与本次话题无关,仅供自己测试 。 
//		 第二个printf结果为4说明int转为了float(4字节),而非int和float都转为了double(8字节)
}



三、一些教材上的错误的用法来源 与 K&R(非正式)标准


float + float → double,int + float → double的用法来源于由C语言设计者丹尼斯·里奇于1978 年出版的《The C Programming Language》第 1 版。笔者暂未找到第一版的资源。


此时的 C 语言还没有统一的标准,来自C语言之父的《The C Programming Language》第 1 版可算作“正式”的标准,所以此时的 C 也称为“K&R” C。


当时的教材就是根据这本书作为标准而编写的。


10年后的1988年,C语言之父丹尼斯·里奇出版了《The C Programming Language》第 2版(如下面的四张图),书中将原用法更改为float + float → float , int + float → float 。(原文:修改了“普通算术类型转换”,特别地,“整型总是转换为unsigned 类型,浮点数总是转换为 double 类型”已更改为“提升到最小的足够大的类型”。)






1989年,考虑到标准化的重要,ANSI(American National Standards Institute)制定了第一个 C 标准,在1989年被正式采用(American National Standard X3.159-1989),故称为 C89,也称为 ANSI C。


该标准随后被 ISO 采纳,成为国际标准(ISO/IEC 9899:1990)。


最后,笔者想吐槽一句:30多年前早已被废弃的用法,这都1202年了,一些教材居然还不修改 ~~


四、参考博文

1. 出现矛盾:c语言中float会自动转换为double? - 知乎

https://www.zhihu.com/question/51829080/answer/1219171602

2.C语言标准—C89、C99、C11、C17、C2x ...

https://blog.csdn.net/lu_embedded/article/details/115535432

3.C2x将成为C语言的下一个ISO标准?:

https://blog.csdn.net/cpongo4/article/details/89030403

4.c语言之标准(K&RC 、c89、c99、c11)

https://blog.csdn.net/qq_31029351/article/details/53290990

5.如何使DEV C++支持C99标准?

https://blog.csdn.net/qq_40834200/article/details/104714963

五、C语言标准各个版本PDF下载

【阿里云盘】

https://www.aliyundrive.com/s/ZfaViMu1Xru

【百度网盘】

链接:https://pan.baidu.com/s/1g6nrTMWUtWr-6VdzGeAjMw

提取码:1234

--来自百度网盘超级会员V1的分享

(完)