目录
前言
一、官方标准证明(C89、C99、C11)
1.C89
2.C99
3.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 C和ANSI 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?
出现矛盾:c语言中float会自动转换为double? - 知乎
五、C语言标准各个版本PDF下载
【阿里云盘】
阿里云盘分享
【百度网盘】
链接:百度网盘 请输入提取码
提取码:1234