编译器怎么编译整数类型的呢?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译器怎么编译整数类型的呢?相关的知识,希望对你有一定的参考价值。
编译器是靠公式还是说里面有个数据表0-9个字符对应的二进制码,然后当翻译源代码的时候,如果读到整数类型,就去按照数据表里提前设定好的二进制做个转换,是这样的吗?
因为源代码都是在文本里写的,那保存时候都是字符。那里面的数值此时也还是字符的二进制保存的,并不是字符数值本身,那编译器根据语法规则,读到这是一个整数类型的字符,通过什么手段就能把字符零0011 0000变成数值0的二进制00000000这样的?
如果是按列表或者数据表,一一对应做转换,那如果一个整数是12,怎么转换?是先把1和2按数据表分别转成对应的数值二进制,然后把1在乘以10,在加上2,变成数值12吗?
识别后的 数(整数,浮点数)转换成2进制格式
识别后的标识符,字符串,还是字符串
识别后的符号有可能转换成整型数据
编译器为他们建一个各表,存储他们的类型,内容等等信息,并为他们分配适当的存储空间。
当编译完成后,需要的信息会写入目标代码。
不需要的信息会被丢弃。
链接器把目标代码链接成可执行程序。
编译器是分阶段识别的;
分为词法分析,语法分析,语义分析,最后是代码生成。
1)先分割出来
2)识别
3)转换
4)代码生成追问
那编译器怎么把字符转成字符本身数值的二进制,是根据公式吗还是别的什么?
追答应该和itoa差不多10进制字符串转换成2进制整型或浮点型,和自已实现的10进制转2进制差不多!另外c还有8,16进制的数,应该也没有太好的办法,和手工实现的差不多!
最多像排序那样,快速排序,虽然快,最坏时间还是O(N^2)
冒泡虽然慢,也是 最坏时间还是O(N^2)
C/C++的源代码是文本文件,编译器最先读到的一定是变量的名称,所以会根据给定类型分配存储空间,各个变量会组成一个变量表,存取变量时,会根据这个来表操作。
如果读到的变量未经初始化,非静态变量的存储单元内不会做任何处理,所以这时存储的是随机值(大都是绝对值很大的负值),如果进行了初始化,会将字符形式的数字串转换为数值,并以二进制(也只有二进制)的形式存放到指定的单元。
如果读到的字符或字符串,则会以ASCII保存在存储单元中。追问
这样啊,那在问下,会将字符形式的数字串转换为数值,这句我想知道转换过程,编译器怎么处理的,你看假设0的字符现在要转成0的数值(也就是0011 0000转成0000 0000),因为0-9的字符编码有个规律,只要把字符串高4位全变成0,就是字符本身的值了,编译器是用这种方法处理的吗?还是编译器有个数据表,里面写好的0-9对应的二进制,然后在把二进制数值存到指定单元?
追答'0' = 0011 0000
'1' = 0011 0001
............
'9' = 0011 1001
都减掉'0'就编程数值了。
比如'7' - '0' = 7
你说的这个公式我知道,这个公式似乎还出现在计算器程序里,原来编译器在处理int类型时候是调用这个公式翻译成整数后,然后写入指定单元的啊?
追答这是为了书写方便,且具有良好的可读性,其实,都减去数值48就是了,CPU做这样的事很轻松的。
追问但是编译器是最底层的,负责翻译整数类型,所以在编译器里写的公式只能写成减去'0',不能写成48,因为编译器不能自己翻译自己,但是开发程序的时候比如计算器里,就可以写成减去48,因为它有编译器可以翻译整数类型,我这么理解对吗?
追答编译器是将源代码转换为.OBJ文件,称作目标代码,经过连接后才能形成CPU认识的机器码。编译器大都是用C编写的,当然也会借助宏汇编(MASM)。
追问那在写编译器时候,公式里到底是写减48还是'0'?还是说最早的第一个编译器里公式只能写'0',然后以后在开发的任何编译器可以直接写48? 还有是不是源代码里的数值最后都是靠编译器里你刚才说的那个公式翻译得到的?然后公式又是根据字符值'0'的特性弄出来,所以可以理解为数值类型是根据字符值运算出来的,因为底层电路可以根据'0'这样的类型进行运算,这样我们就可以得到字符本身的数值了,帮我看看理解的有误吗
追答这样吧,你找一本《编译原理》看看,那里有你需要的很多内容。在这里一时半会儿很难解释明白的。
追问我倒不是想全面了解编译原理,就是想知道整数的转换过程这块,你前面说的那个公式我能明白,我明白了本身编译器也是个程序,那在公式里可以直接写48,因为编译器也是被汇编编译器翻译过的,那你说第一个编译器呢,应该是机器码写的了吧,那时候应该不能直接写48了吧?你大概在帮我讲两句吧谢谢,也不用很复杂,我就想了解数值转换这块
追答你的执着令人佩服。
第一台计算机是用电子管、碳膜电阻、铝电解电容器等原始器件组装的,后来使用晶体三极管,体积极具减小,即使这样,也得有几十平方的房子才装得下,再后来,集成电路、大规模集成电路和超大规模继承电路的发展,才将电子计算机发展到现在电脑(微型计算机)。
第一台及其问世时,编程语言只有机器码一种,当然机器指令很少,功能也及其有限,只能深藏于大房子内,供几个人研究使用。为了扩大用途用户面,科学家发明了汇编语言(助记符)语言,这是搞科学研究的科技人员才能涉足计算机编程,这样的语言还不能满足用户的要求,原因是难以记忆,编程很困难。助记符相对机器语言来说,已经进了一大步,但助记符语言不能过被CPU识别,此时,就需要将助记符转换成机器指令,以便于计算机执行,这个完成转换软件就是编译器了。
晶体管这些我知道,但是你没说整数转换那块,助记符里有代表整数的吗,难道用00000000代表整数0?用助记符1代表整数0000 0001?要是真这样那道省事了,编译器还要什么公式,直接写1就是int类型了1.
追答电脑操作是以Byte(字节)为单位的,每个字节含有8个二进制位。CPU可以产生立即数(也就是你说的整数),编译器会利用这样的机器指令生成需要的内容。
追问那在问下编译器里公式也 能这么写吗7-0 = 7?因为编译器也是汇编编译器翻译好的是吧?
追答不行,应该用汇编语言,如
MOVE AX,7
MOVE BX,0
SUB AX,BX
此后,AX中存放的是AX - BX的结果。
BYTE HexChar2Number(char c)
if('0' <= c && c <= '9')
return (BYTE)(c - '0');
if('A' <= c && c <= 'F')
return (BYTE)(c - 'A' + 10);
if('a' <= c && c <= 'f')
return (BYTE)(c - 'a' + 10);
printf("error char: %c\n", c);
return 0;
逐字符识别,识别多位数时自己乘以进制权值。
Java throws子句是怎么写的呢?
如果一个方法可以导致一个异常但不处理它,它必须指定这种行为以使方法的调用者可以保护它们自己而不发生异常。做到这点你可以在方法声明中包含一个throws子句。一个 throws 子句列举了一个方法可能抛出的所有异常类型。这对于除Error或RuntimeException及它们子类以外类型的所有异常是必要的。一个方法可以抛出的所有其他类型的异常必须在throws子句中声明。如果不这样做,将会导致编译错误。
下面是包含一个throws子句的方法声明的通用形式:
type method-name(parameter-list) throws exception-list{
// body of method
}
这里,exception-list是该方法可以抛出的以有逗号分割的异常列表。
下面是一个不正确的例子。该例试图抛出一个它不能捕获的异常。因为程序没有指定一个throws子句来声明这一事实,程序将不会编译。
// This program contains an error and will not compile.
class ThrowsDemo {
static void throwOne() {
System.out.println("Inside throwOne.");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) {
throwOne();
}
}
为编译该程序,需要改变两个地方。第一,需要声明throwOne( )引发IllegalAccess Exception异常。第二,main( )必须定义一个try/catch 语句来捕获该异常。正确的例子如下:
// This is now correct.
class ThrowsDemo {
static void throwOne() throws IllegalAccessException {
System.out.println("Inside throwOne.");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) {
try {
throwOne();
} catch (IllegalAccessException e) {
System.out.println("Caught " + e);
}
}
}
下面是例题的输出结果:
inside throwOne
caught java.lang.IllegalAccessException: demo
以上是关于编译器怎么编译整数类型的呢?的主要内容,如果未能解决你的问题,请参考以下文章