在编译器/机器级别执行什么操作?

我经常想知道在编译器或机器级别上做什么。 它与内存中的0和1有什么关系?

任何人都可以指出一些好的文献。

在引用类型之间进行转换时,转换不会修改各个位,它只是指示编译器/运行时在可能的情况下以特定方式解释这些位。

如果由于类型不兼容而在编译时无法进行强制转换,则会发出错误。 如果在运行时无法进行强制转换,则抛出exception。

类型转换的Wiki页面包含其他信息。

在C中,对于非数字类型,转换在内存中的0和1上不执行任何操作。

对于数字类型,C编译器进行转换,以使数值尽可能保持不变。

如果你想在不改变位值的情况下转换数值类型,你必须使用union或cast指针(下面的代码说明了后者):

float a; int b = 3; a = *((float*)&b); 

关于Casting,一个有用的文献将是JavaTM虚拟机规范

在转化和促销部分,您会看到有六种广泛的转化:

  • 身份转换
  • 扩大原始转换
  • 缩小原始转换
  • 扩大参考转换
  • 缩小参考转换
  • 字符串转换

转换表达式有五种转换上下文,包括转换转换 :

转换上下文允许使用:

  • 身份转换,
  • 一个扩大的原始转换,
  • 缩小的原始转换,
  • 扩大参考转换,或
  • 缩小参考转换。

因此,转换转换比赋值转换或方法调用转换更具包容性:转换可以执行除字符串转换之外的任何允许转换。

强制转换可以将任何数字类型的值转换为任何其他数字类型。 boolean类型的值不能转换为其他类型。 引用类型的值不能转换为基本类型的值。

某些强制转换在编译时可能被certificate是错误的,并导致编译时错误。 否则,可以在编译时certificate转换正确,或者需要运行时有效性检查。 (有关详细信息,请参阅JavaTM语言规范 。)
如果运行时的值是空引用,则允许转换。 如果运行时检查失败,则抛出ClassCastException。

假设这只是一个引用类型转换而不是转换(例如int到byte),我相信它会执行以下操作:

1)检查引用是否为空 – 如果是,则退出。 2)按照引用查找内存中的对象。 在对象标题中,有信息说明类型是什么。 3)从类型信息中,检查目标类型是否在层次结构中。 如果不是,请使用适当的信息抛出ClassCastException

结果的“位”始终与输入的“位”相同(假设有输出而不是exception),但JVM知道引用的类型,因此保证其他操作成功。

还需要了解引用在编译和运行时的工作方式。

每种类型都为每个方法保存一个查找表,该方法将每个方法解析为该类型的最佳解析方法。

因此,如果您的引用是一个对象,则调用toString()会做正确的事情并找到派生最多的toString()方法。 必须进行转换以允许运行时保证任何给定的引用确实具有针对引用上公开的每个方法的目标方法。 在将转换从X传递到Y之后,任何类型Y的引用都可以确保其所有方法都可用于转换(sp)引用。

其他人已经介绍了基础知识,但我想谈谈如何实现编译器,这可能对他的情况有启发意义。

编译器维护程序中任何特定点使用的变量名称列表(称为符号表 )以及有关变量的一些信息。 信息列表包括:

  • 他们分配的存储空间(在此寄存器中,在该存储器位置等)
  • 它们是什么类型(即整数或字符串或SubWhatsitObj ),包括任何限制(例如常量)
  • 编译器需要的任何链接信息

编译器使用此信息来决定如何处理涉及变量的表达式。 存储在符号表中的元信息的类型也可以从其组件的任何表达式导出。

除了数值类型转换的特殊情况之外,强制转换只是告诉编译器对变量或表达式使用不同的元信息,而不是通常情况。 内存中的任何位都没有受到影响,但计算的结果可能是。

这取决于你的演员。 对于数字强制转换(浮动到int和后退),CPU将尝试查找最适合目标的数字。

对于类型的情况,它对记忆没有任何作用。 这只是软件开发人员告诉愚蠢的编译器一种方式应该将某个变量视为不同类型的一种方式。

我试图谷歌关于数字投射规则的一些信息,但没有太多。 您可以尝试C99标准,但我不确定它是否会让您感到压力。 IIRC,规则是:

  • 向下转换(大类型 – >较小类型,如double – > float – > int – > byte)将切断无法表示的信息(因此double-> float将失去精度, – > int将丢失所有小数位+没有四舍五入)。

  • 强制转换(较小类型 – >较大类型)意味着用“0”填充其他位。

当然,有些数字你无法真正代表 (如0.1)。 即使没有铸造,对它们的任何操作都将丢失信息(这就是为什么0.1 * 10可以!= 1.0)。