1、首先,C语言是编译型语言,而不是解释型或者实时编译。初学者往往分不清C代码中,那些是编译期信息,哪些出现在可执行程序。“不幸”的是,类型就是编译期才有的信息,运行代码的时候并不存在类型。
2、对于C语言,类型是一种编译期抽象,而不是一种存在。比如,如果你声明一个int a,接下来对a的操作都被编译为整型运算指令(比如mov/锾攒揉敫add/inc等)。如果你声明一个float a,接下来对a的操作都被编译成可以计算浮点的指令(比如movss/addss等)
3、我们来查看 类型 a; a=0; ++a; 这三行代码产生的机器码(汇编)。请注意到,int a和float a这两个声明都不对应任何机器代洁船诼抨码。声明int a后,a=0 被编译为: mov dword ptr [a],0声明float a后,a=0 被编译为:xorps xmm0,xmm0 和 movss dword ptr [a],xmm0
4、同理,下面的代码依次翻译如下。请注意:编译器根据a的类型声明不同,在产生的机器码中,把他们移动到了不同的寄存器,使用了不同的运算指令。
5、数据类型是抽象,只是为了方便编程。编译期类型检查是为了:防止程序员搞混,对一个数据一会使用整型运算,一会又进行浮点运算,得到毫无意义的错误结果。
6、这些数据在内存中无非都是一个字节一个字节的普通数据,并不带有标签,说什么这个是整型那个是浮点型。对于同样的数据,按照float类型来看和按照int类型来看,数值是大相径庭的。
7、编译器的类型检查,保证了我们产生的机器码,始终对内存中某4字节数据进行整型操作,对另外的某4字节数据始终进行浮点型操作,免得混淆掉。
8、对于函数的重载现象,我们确实可以使用int func猾诮沓靥(int x){…} float func(float x){…} double func(double x){…}来根据输入剞麽苍足数据的类型不同而调用不同的函数,但是请追根溯源,你就会发现,调用那个函数其实是编译期决定了的。重载是减轻人的记忆负担,不信的话,你把它们命名为int funcInt(int x){…} float funcFloat(float x){…} double funcDouble(double x){…}由你自己来做一回C编译器,决定该调用那个函数,你会发现任何一处调用地点都不会出现任何if语句就可以确定每次调用那个函数。
9、有时候,如果我们非要对类型进行判断(这种情况在初级阶段是遇不到的),可以使用如下普遍采用的形式,就是始终用另外一个变量来标记数据的“类型”。比如自己定义一个TYPE类型,用以传递类型数据。在C语言中,永远都不能指望从一个变量本身不加额外信息获取类型。