C++-VC++中的编译是指执行什么工作?除了检查语法外,还有什么作用?例如下面不完整程序提出的有那类错误?

发布于 2016-10-30 15:55:57 字数 840 浏览 1211 评论 6

#include <iostream>
using namespace std;

//定义结构体(放在文件头方便管理)
typedef char ElemType;
typedef struct LNode
{
ElemType data;
struct LNoode *next;
}LNode,*LinkList;
typedef int status; //函数结果状态代码

#define OK 1
#define ERROR 0
#define NULL 0

//初始化
status LinkList_L(LinkList &L)
{
L=new LNode;
if(!L) return ERROR;
L->next=NULL;
return OK;
}

//把e插入到i位置
status LinkInsert_L(LinkList &L,int i,ElemType e)
{
LNode *p,*s;
int j=0;
p=L;
while(p&&j<i-1) { p=p->next; ++j; }
if(!p||j>i-1) return ERROR;
s=new LNode;
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

甜柠檬 2017-09-21 08:35:52

总体上来说,编译分为5个阶段
1、词法分析
2、语法分析
3、语言分析
4、中间语义生成
5、目标代码生成与优化
检查语法错误是在语法分析阶段做的事情,后面还要生成可目标文件,以便在连接阶段,可以连接生成可执行文件,最后由装载器装载到内存 执行

瑾兮 2017-09-15 00:10:39

编译过程一般可以分为6步:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化。如下所示:

1. 词法分析(扫描):
运用有限状态机(Finite State Machine)可以轻松的将源代码的字符序列分割成一系列的记号。此法分析产生的记号一般有一下几类:关键字、标识符、字面量(包含数字、字符串等)和特殊符号(如加号、等号)

2. 语法分析:
语法分析器(Grammar Parser)将对由扫描器产生的记号进行语法分析,从而产生语法树。由语法分析器生成的语法树就是以表达式为节点的树。

3. 语义分析:

编译器所能分析的语义是静态语义,所谓静态语义是指在编译期间可以确定的语义,与之相对应的动态语义,就是在运行期才能确定的语义。

4. 源代码优化

5. 代码生成

6. 目标代码优化

浮生未歇 2017-09-10 20:15:16

C++的编译是把C++源代码切割、优化翻译成二进制文件,只要这段代码没有语法错误那都是能编译的。编译出来的二进制文件(比如COFF)中包含这个源代码中的所有的代码。也就是说,在编译过程中,LZ这段代码是不会有问题的。
但是,VC在编译之后还会进行链接(除非你编译的是静态库lib文件),把所有".cpp"编译出来的二进制文件链接成可执行文件(.exe)或者动态链接库(.dll)之类的文件。在这个过程中,VC找不到默认的程序入口点(这个可以再选项里面设置,比如_tmain,main,_WinMain什么的),所以链接过程会失败,找不到symbol main或者_tmain之类的。错误编号LNK2001貌似。。

清晨说ぺ晚安 2017-06-09 22:04:46

上述代码除了第9行的LNode写错了之外,就没有问题了,修改一下就能够在VS2008中编译通过。
但是链接或报错,因为没有main函数。

1>------ 已启动生成: 项目: test30, 配置: Debug Win32 ------
1>正在链接...
1>LINK : fatal error LNK1561: 必须定义入口点

编译:编译器对源代码进行编译,是将以文本形式存在的源代码翻译为机器语言形式的目标文件的过程。
对于C++来说,每一个cpp文件就是一个编译单元。从之前的编译过程的演示可以看出,各个编译单元之间是互相不可知的。
目标文件:由编译所生成的文件,以机器码的形式包含了编译单元里所有的代码和数据,以及一些其他的信息。

编译完成之后需要进行链接:
链接器进行链接的时候,首先决定各个目标文件在最终可执行文件里的位置。然后访问所有目标文件的地址重定向表,对其中记录的地址进行重定向(即加上该编译单元实际在可执行文件里的起始地址)。然后遍历所有目标文件的未解决符号表,并且在所有的导出符号表里查找匹配的符号,并在未解决符号表中所记录的位置上填写实际的地址(也要加上拥有该符号定义的编译单元实际在可执行文件里的起始地址)。最后把所有的目标文件的内容写在各自的位置上,再作一些别的工作,一个可执行文件就链接完成了。

整个过程如下图:

参考资料:
编译器和连接器的工作原理

瑾兮 2017-01-20 06:58:36

正如楼上所说的那样
举个简单的例子,例如:
void f();

int main() {
f(); //找不到函数的定义,连接错误。
return 0;
}

这样单纯的编译不会报错,是连接错误。找不到函数的定义。
但是如果你把 void f();注释掉。如下:
int main() {
f();

return 0;
}
这样编译就会报错了。连f的声明都没有编译就会报错。
VC提示信息error C3861: 'f': identifier not found
f这个标识符没有找到。

晚风撩人 2016-12-26 22:41:54

编译之后,还会进行链接的操作。VC中默认会链接程序的入口,即是main函数,如果找不到的话会报Link error。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文