我经常想知道在编译器或机器级别上进行什么操作。它对内存中的0和1有什么作用?
有人能指出一些好的文献。
答案 0 :(得分:6)
在引用类型之间进行转换时,转换不会修改各个位,它只是指示编译器/运行时在可能的情况下以特定方式解释这些位。
如果由于类型不兼容而在编译时无法进行强制转换,则会发出错误。如果在运行时无法进行强制转换,则抛出异常。
答案 1 :(得分:2)
在C中,对于非数字类型,转换在内存中的0和1上不执行任何操作。
对于数字类型,C编译器进行转换,以使数值保持尽可能相同。
如果你想在不改变位值的情况下转换数值类型,你必须使用联合或转换指针(下面的代码说明了后者):
float a;
int b = 3;
a = *((float*)&b);
答案 2 :(得分:2)
关于Casting,有用的文献是JavaTM Virtual Machine Specification。
在Conversions and Promotions部分,您会看到有六种广泛的转化:
转化表达式有五种转换上下文,包括Casting Conversion:
投射上下文允许使用:
- 身份转换,
- 扩大基元转换,
- 缩小基元转换,
- 扩大参考转换,或
- 缩小参考转换。
因此,转换转换比赋值转换或方法调用转换更具包容性:转换可以执行除字符串转换之外的任何允许转换。
强制转换可以将任何数字类型的值转换为任何其他数字类型。 boolean类型的值不能转换为其他类型。引用类型的值不能转换为基本类型的值。
某些强制转换在编译时可能被证明是错误的,并导致编译时错误。否则,可以在编译时证明强制转换是正确的,或者需要运行时有效性检查。 (有关详细信息,请参阅JavaTM Language Specification。)
如果运行时的值是空引用,则允许转换。如果运行时检查失败,则抛出ClassCastException。
答案 3 :(得分:1)
假设这只是一个引用类型转换而不是转换(例如int到byte),我相信它会做到以下几点:
1)检查引用是否为null - 如果是,则退出。
2)按照引用查找内存中的对象。在对象标题中,有信息说明类型是什么。
3)从类型信息中,检查目标类型是否在层次结构中。如果不是,请使用适当的信息抛出ClassCastException
。
结果的“位”始终与输入的“位”相同(假设 是输出而不是异常),但是JVM知道输入的类型参考,以保证其他操作成功。
答案 4 :(得分:1)
这取决于你的演员。对于数字转换(浮动到int和后退),CPU将尝试找到最适合目标的数字。
对于类型情况,它对记忆没有任何作用。这只是软件开发人员告诉愚蠢的编译器应该将某个变量视为不同类型的一种方式。
我试图谷歌关于数字投射规则的一些信息,但没有太多。你可以尝试C99 standard,但我不确定它是否会让你感到压力。 IIRC,规则是:
向下转换(大型 - >较小的类型,如double - > float - > int - > byte)将切断无法表示的信息(因此double-gt; float将丢失精度, - > int将丢失所有小数位+没有舍入)。
强制转换(较小的类型 - >较大的类型)意味着用'0'填充其他位。
当然,你有can't really represent的数字(如0.1)。即使没有施放,对它们的任何操作都将丢失信息(这就是为什么0.1 * 10可以是!= 1.0)。
答案 5 :(得分:1)
还需要了解引用在编译和运行时的工作方式。
每种类型都为每个解析的方法保存一个查找表 每种方法都是该类型解析最多的方法。
因此,如果您的引用是一个对象,则调用toString()会做正确的事情并找到派生最多的toString()方法。必须进行转换以允许运行时保证任何给定的引用确实具有针对引用上公开的每个方法的目标方法。将强制转换从X传递给Y之后,任何类型为Y的引用都可以确保其所有方法都可用于铸造(sp)引用。
答案 6 :(得分:1)
其他人已经介绍了基础知识,但我想谈谈编译器的实现方式,这可能对他的案例具有启发意义。
编译器维护一个在程序中任何特定点使用的变量 names 的列表(称为符号表)以及有关变量的一些信息。信息列表包括:
SubWhatsitObj
),包括任何限制(例如常量)编译器使用此信息来决定如何处理涉及变量的表达式。存储在符号表中的元信息的类型也可以从其组件的任何表达式派生。
除了数值类型转换的特殊情况之外,强制转换只是告诉编译器对变量或表达式使用不同的元信息,而不是通常情况。内存中的任何位都没有受到影响,但计算的结果可能是。