⑴ 编译原理:优先函数 f和g 到底怎么看啊,不懂怎么构造的 求解...
求算符优先函数的方法—迭代法
若已知运算符之间的优先关系,可按如下步骤构造优先函数:
1、对每个运算符a(包括#在内)令f(a)=g(a)=1
2、如果a⋗b且f(a)<=g(b),令f(a)=g(b)+1
3、如果a⋖b且f(a)>=g(b),令g(b)= f(a)+1
4、如果a≐b而f(a) ≠g(b),令min{f(a),g(b)}=max{f(a),g(b)}
5、重复2~4,直到过程收敛。如果重复过程中有一个值大于2n,则表明不存在算符优先函数。
⑵ C语言编译原理是什么
编译共分为四个阶段:预处理阶段、编译阶段、汇编阶段、链接阶段。
1、预处理阶段:
主要工作是将头文件插入到所写的代码中,生成扩展名为“.i”的文件替换原来的扩展名为“.c”的文件,但是原来的文件仍然保留,只是执行过程中的实际文件发生了改变。(这里所说的替换并不是指原来的文件被删除)
2、汇编阶段:
插入汇编语言程序,将代码翻译成汇编语言。编译器首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,编译器把代码翻译成汇编语言,同时将扩展名为“.i”的文件翻译成扩展名为“.s”的文件。
3、编译阶段:
将汇编语言翻译成机器语言指令,并将指令打包封存成可重定位目标程序的格式,将扩展名为“.s”的文件翻译成扩展名为“.o”的二进制文件。
4、链接阶段:
在示例代码中,改代码文件调用了标准库中printf函数。而printf函数的实际存储位置是一个单独编译的目标文件(编译的结果也是扩展名为“.o”的文件),所以此时主函数调用的时候,需要将该文件(即printf函数所在的编译文件)与hello world文件整合到一起,此时链接器就可以大显神通了,将两个文件合并后生成一个可执行目标文件。
⑶ c与c++语言编译器是如何识别关键字
根据编译器的不同,有不同的识别方式,例如VC6.0使用系统内建关键字列表,如果用户定义变量的时候使用了系统默认的关键字,则会在编译的时候产生错误。
附上:
C语言的关键字共有32个,根据关键字的作用,可分其为数据类型关键字、控制语句关键字、存储类型关键字和其它关键字四类。
1 数据类型关键字(12个):
(1) char :声明字符型变量或函数
(2) double :声明双精度变量或函数
(3) enum :声明枚举类型
(4) float:声明浮点型变量或函数
(5) int: 声明整型变量或函数
(6) long :声明长整型变量或函数
(7) short :声明短整型变量或函数
(8) signed:声明有符号类型变量或函数
(9) struct:声明结构体变量或函数
(10) union:声明联合数据类型
(11) unsigned:声明无符号类型变量或函数
(12) void :声明函数无返回值或无参数,声明无类型指针(基本上就这三个作用)
(2)控制语句关键字(12个):
A循环语句
(1) for:一种循环语句(可意会不可言传)
(2) do :循环语句的循环体
(3) while :循环语句的循环条件
(4) break:跳出当前循环
(5) continue:结束当前循环,开始下一轮循环
B条件语句
(1)if: 条件语句
(2)else :条件语句否定分支(与 if 连用)
(3)goto:无条件跳转语句
C开关语句
(1)switch :用于开关语句
(2)case:开关语句分支
(3)default:开关语句中的“其他”分支
D
return :子程序返回语句(可以带参数,也看不带参数)
3 存储类型关键字(4个)
(1)auto :声明自动变量 一般不使用
(2)extern:声明变量是在其他文件正声明(也可以看做是引用变量)
(3)register:声明积存器变量
(4)static :声明静态变量
4 其它关键字(4个):
(1)const :声明只读变量
(2)sizeof:计算数据类型长度
(3)typedef:用以给数据类型取别名(当然还有其他作用
(4)volatile:说明变量在程序执行中可被隐含地改变
⑷ 编译原理的实质
计算机程序编译原理的实质就是把程序员员容易理解的高级语言程序代码流翻译成计算机可执行的机器指令代码流。可以使用“一断、二比、三译”形象说明实质。
1、断。按照语言的语法规则扫描断词,结合文法词典把程序字符串流分解成为计算机语言能够识别的基本单元(标识词、运算符)。
2、比。从程序流中找出扩展标识词的定义,建立标识词结构,放入文法词典,服务于新的定义和函数程序代码的编译。程序语句、表达式里面使用的标识可以从词典中比较找到。
3、译。把函数程序文本字符串流中的算术表达式、赋值语句、控制语句翻译成为计算机机器语言二进制代码流。
4、组装函数翻译后的二进制代码流,明确数据空间地址和大小,生成计算机裸机或操作系统可以执行目标代码。
⑸ C 如何识别函数
#include <string.h>
#include <stdio.h>
//如果你用的是VC6,这个宏对于习惯标准语法的人很管用
#define for if(false);else for
// 这只是一个非常简单的例子,具体你还是需要自己修改来满足跟复制的需求
// 这个函数会直接修改tempstr,将字符串中的分隔符替换为\0
// tempstr:临时字符串
// delimitChars:包含各种分隔字符的字符串
// tokens:用于接收分割后的字符串指针的数组
void strSplit(char * tempstr, const char *delimitChars, char *tokens[])
{
tokens[0]=NULL;
if(tempstr==NULL)
return;
tokens[0]=tempstr;
for(size_t pos=0,i=0;tempstr[pos]!='\0';)
{
tokens[i++]=tempstr+pos;
pos=pos+strcspn(tempstr+pos,delimitChars);
if(tempstr[pos]=='\0')
break;
tempstr[pos++]='\0';
}
}
int main()
{
//由于传递给strSplit的字符串必须是可修改的,所以这里将字符串存储在字符数组中,注意这跟char *tempstr="123;34;;56"是不一样的
char tempstr[100]="shiting;;pig";
//一个指针数组,用于存储分割后的字符串指针
char* tokens[8]={};
//这个函数执行后,tempstr的内容被修改为"shiting\0\0pig"
//所以在必要的时候你应该传递一份拷贝给这个函数
strSplit(tempstr,";",tokens);
//打印分割后的字符串
for (int i=0;tokens[i]!=NULL;i++)
{
printf("%s\n",tokens[i]);
}
return 0;
}
⑹ 一直有个疑惑,C/C++编译器是如何调用函数的
函数的调用就是 跳转到函数体的入口地址。
函数体本身的存储空间是在exe里txt段,然后运行加载的时候映射到地址空间。不过看你的问题,你关注的不是这个的占用。
关于你问的问题, 其实是因为一旦定义了虚函数,在C++类型的头部,就会有一个指针的隐藏变量被定义,从而该类型的每个对象都会有这个变量的大小。 这个只有类型有和没有虚函数的区别,虚函数的个数造成内存增长只是虚表里(每class一个),每个对象里只是存的一个指针,不会有size变化。
对于非虚的函数,编译的时候,直接就是填写的函数体的入口地址; 而虚函数,则是要经过计算,先通过对象头部寸的虚表指针找到虚表,再去找对应的虚表项 ,里面存储的就是需要的函数的入口地址。
建议楼主看看 C++布局方面的书,比如 <Inside C++ Object Model>, 以及平时多用VS操练一下调试技巧,然后适当熟悉简单的汇编代码,对融会贯通很有帮助。
⑺ 优先函数是什么编译原理
构造算符优先分析表时使用的优先函数,其等价于矩阵表,但存储量小。
定义两个函数,其对应元素的值为优先值,通过循环比较各元素的两个值,每次将优先级大的值改为小的值+1,若相等则都赋为目前较大的值,循环直至结果没有变化,构造OK
⑻ 如何用C语言识别一个C程序的注释和函数
/* */ 主要是字符匹配的问题,检索 / 和 * ,如果检索到 * 和 / ,哨兵变量为 1 ,否则为 0 ;
//主要是检索到 / 和 / 就可以,以后这一行都是注释了。
头一个注释可以应用于 printf 中,后者不可以。
---------------------
以上均是个人理解,如有错误,请高手指正。