本文由wo_相当厉害贡献
ppt文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。
Linux下的C/C++程序设计
Linux下的C/C++程序设计介绍 gcc编译系统 gdb程序调试工具 Linux下的窗口程序设计 (QT程序设计)
1. Linux下的C/C++程序设计介绍
Linux是一个开放源代码的操作系统,其稳定 性与低廉的价格使其在服务器、嵌入式领域 以及桌面应用中逐渐占有越来越大的市场份 额。因此,对Linux环境下的程序开发人员的 需求也就越来越大了。 C语言是Linux操作系统中的核心语言,掌握 Linux环境下的C语言开发是至关重要的。
Linux下的C/C++程序设计介绍
Linux编程实现步骤: $ vi hello.c 按下I进入编辑状态 输入以下内容 #include main() { printf(“I try to use linux! \n”); echo “echo also can be used for output。\n” }
Linux下的C/C++程序设计介绍
Linux编程实现步骤: 按ESC进入命令状态 输入:“:wq” 保存文件并退出 $ gcc -o hello.out hello.c
编译hello.c ,将并将文件输出到hello.out
$ ./hello.out 你将会看到输出结果
I try to use linux! echo also can be used for output。 $
2. gcc编译系统
GNU Compiler Collection, Richard Stallman, since 1987
一套多语言,多平台的编译器/链接器软件集合 Version 4.0支持Ada (GCC for Ada aka GNAT), C, C++ 4.0 Ada (GCC for C++ aka G++), Fortran (GCC for Fortran aka GFortran), Java (GCC for Java aka GCJ), Objective-C 主要支持平台:Alpha, ARM, Blackfin, System/390, x86 and AMD64, the "Itanium“, Motorola 68000, MIPS, PowerPC, SPARC
Windows下的GCC环境
dev-c++, using MinGW
2. gcc编译系统(续)
目前Linux平台上最常用的C语言编译系统是gcc(GNU Compiler Collection) 常用文件名后缀及其表示的文件类型
文件名后缀 .c .i .ii .h .C .cc .cp .cpp .c++ .cxx .s .S .o .a .so 文件类型 C源文件 预处理后的C源文件 预处理后的C++源文件 C或C++头文件 C++源文件 汇编程序文件 必须预处理的汇编程序文件 目标文件 静态链接库 动态链接库
2. gcc编译系统(续)
gcc命令的工作过程
1.预处理阶段
预处理程序(Preprocessor)读取C语言源文件,对其中以“#”开头的指 令(伪指令)和特殊符号进行处理。 伪指令主要包括文件包含、宏定义和条件编译指令。
2.编译阶段
编译程序(Compiler)对预处理之后的输出文件进行词法分析和语法分 析,试图出所有不符合语法规则的部分。在确定各成分都符合语法规 则后,将其“翻译”为功能等价的中间代码表示或者汇编代码。
3.汇编过程
汇编程序(Assembler)把汇编语言代码翻译成目标机器代码的过程。
4.连接阶段
将一个文件
中引用的符号(如变量或函数调用)与该符号在另外一个文 件中的定义连接起来,从而使有关的目标文件连成一个整体,最终成为 可被操作系统执行的可执行文件。 连接模式分为静态连接和动态连接。
2. gcc编译系统(续)
gcc指令的一般格式为:
gcc [参数] 要编译的文件 [参数] [目标文件]
$ gcc f1.c f2.c (针对C语言源程序)执行完成后,生成默认的可执 行文件a.out。 按照选项作用所对应的编译阶段,可将gcc的选项分为四组:预处理选项、 编译选项、优化选项和连接选项。
1.预处理选项
选 项 格 式 -C -D name -D name=definition 功 能 在预处理后的输出中保留源文件中的注释 预定义一个宏name,而且其值为1 预定义一个宏name,并指定其值为definition所指定的值。其作用等价于 在源文件中使用宏定义指令:#define name definition。但-D选项比宏定 义指令的优先级高,它可以覆盖源文件中的定义 取消先前对name的任何定义,不管是内置的,还是由-D选项提供的 指定搜索头文件的路径dir。先在指定的路径中搜索要包含的头文件,若 不到,则在标准路径(/usr/include, /usr/lib及当前工作目录)上搜索 只对指定的源文件进行预处理,不做编译,生成的结果送到标准输出
-U name -I dir -E
2. gcc编译系统(续)
2.编译程序选项
选项格式 功 能
-c -S -o file -g -v
只生成目标文件,不进行连接。用于对源文件的分别编译 只进行编译,不做汇编,生成汇编代码文件格式,其名与源文件相同, 但扩展名为.s file a.out 将输出放在文件file中。如果未使用该选项,则可执行文件放在a.out中 指示编译程序在目标代码中加入供调试程序gdb使用的附加信息 在标准出错输出上显示编译阶段所执行的命令,即编译驱动程序及预处 理程序的版本号
3.优化程序选项
优化分为对中间代码的优化和针对目标码生成的优化。
4.连接程序选项
选 项 格 式 object-file-name -c -S -llibrary -static -Ldir -Bprefix -o file -E 功 能 不以专用后缀结尾的文件名就认为是目标文件名或库名。连接程序可以根据 文件内容来区分目标文件和库 如果使用其中任何一个选项,那么都不运行连接程序,而且目标文件名不应 该用做参数 连接时搜索由library命名的库。连接程序按照在命令行上给定的顺序搜索 和处理库及目标文件。实际的库名是liblibrary.a 在支持动态连接的系统中,它强制使用静态链接库,而阻止连接动态库;而 在其他系统中不起作用 把指定的目录dir加到连接程序搜索库文件的路径表中,即在搜索-l后面列 举的库文件时,首先到dir下搜索,不到再到标准位置下搜索
该选项规定在什么地方查可执行文件、库文件、包含文件和编译程序本身 数据文件 指定连接程序最后生成的可执行文件名称为file,不是默认的a.out
2. gcc编译系统(续)
应用举例
示例源程序——hello.c 示例源程序 #include int main(void) { printf("hello gcc!\r\n"); return 0; }
2. gcc编译系统(续)
linux下gcc编译的四个步骤生成预处理文件命令
$gcc –E hello.c –o hello.i
预处理文件hello.i的部分内容 的部分内容 预处理文件 …… extern void funlockfile (FILE *__stream) ; # 679 "/usr/include/stdio.h" 3 # 2 "hello.c" 2 int main(void) { printf("hello gcc!\n"); return 0;
2. gcc编译系统(续)
生成汇编文件
$gcc –S hello.c –o hello.s
汇编文件hello.s的部分内容 的部分内容 汇编文件 …… main: pushl movl …… addl movl leave ret ……" $16, %esp $0, %eax %ebp %esp, %ebp
2. gcc编译系统(续)
生成目标文件
命令:
$gcc –c hello.c –o hello.o
生成可执行文件
命令:
$gcc hello.c –o hello 运行程序 $./hello hello gcc!
2. gcc编译系统(续)
gcc错误类型及对策
C语法错误:C语言的语法错误 头文件错误:不到头文件head.h 连接库错误:不到所需要的函数库 未定义符号:有未定义的符号
2. gcc编译系统(续)
gcc调试总结
主要为语法错误:
输入错误; 类型匹配错误;
分析信息:
主要来自gcc编译时产生的提示信息
错误警告定位:
不一定在提示信息描述的地方; 综合分析提示信息及提示行的上下文环境,定位并 修正错误、警告。 有的警告可以不用修复;
Makefile的编写
对于大型程序,通常由成千上万个模块(子程序) 组成,在编写过程中,人们希望对其中某个(些) 模块的修改不要导致对整个程序的编译,这也是 Makefile的一个主要功用之一。
Makefile举例
Makefile内容
factorial:main.o factorial.o
gcc –o factorial main.o factorial.o
Makefile简化写法
factorial:main.o factorial.o gcc –o $@ $^ main.o:main.c gcc –c $< factorial.o:factorial.c gcc –c $<
main.o:main.c gcc –c main.c factorial.o:factorial.c gcc –c factorial.c
3. gdb程序调试工具(续)
静态调试:
在程序编译阶段查错并修正错误; 主要为语法错误:
输入错误; 类型匹配错误;
排错方式:
利用错误、警告信息,并结合源文件环境排错
动态调试:
在程序运行阶段差错并修正错误; 主要错误类型:
算法错误; 输入错误;
排错方式:
利用调试工具定位并修正错误;
3. gdb程序调试工具
程序中的错误按其性质可分为三种:
(1)编译错误,即语法错误。主要是程序代码中有不符
合所用编程语言语法规 则的错误。 (2)运行错误。如对负数开平方,除数为0,循环终止条件永远不能达到等 。 (3)逻辑错误。这类错误往往是编程前对求解的问题理解不正确或算法不正确 引起的,它们很难查。
查程序中的错误,诊断其准确位置,并予以改正,这就是程序调试。 程序调试分为人工查错与机器调试。 gdb主要帮助用户在调试程序时完成四方面的工作:
(1)启动程序,可以按用户要求影响程序的运行行为。 (2)使运行程序在指定条件处停止。 (3)当程序停止时,检查它出现了什么问题。 (4)动态改变程序的执行环境,这样就可以纠正一个错误的影响,然后再纠正 其他错误。
3. gdb程序调试工具
gdb概述 gdb概述 Linux下的gdb调试器,是一款GNU组织开发 并发布的UNIX/Linux下的程序调试工具。它 没有图形化的友好界面,但功能强大。 在进行应用程序的调试之前,要注意的是 gdb进行调试的是可执行文件 可执行文件,而不是如 可执行文件 “.c”这样的源代码文件。因此,需要先通 过gcc编译生成可执行文件才能用gdb进行 调试。
3. gdb程序调试工具(续)
完成如下的调试任务:
(1)设置断点。 (2)监视程序变量的值。 (3)程序的单步执行。 (4)修改变量的值。
3. gdb程序调试工具(续)
为了发挥gdb的全部功能,需要在编译源程序时使用-g选项: $ gcc $ gcc -g -g prog.c -o prog (针对C语言源程序prog.c) program.cpp -o program (针对C++源程序program.cpp)
启动gdb的常用方法有:
(1)以一个可执行程序作为gdb的参数: $ gdb prgm (2)同时以可执行程序和core文件作为gdb的参数: $ gdb prgm core 启动gdb后就显示其提示符:(gdb),并等待用户输入相应的内部命令。 (gdb) 用户可以利用命令quit quit终止其执行,退出gdb环境。 quit
3. gdb程序调试工具(续)
启动gdb
3. gdb程序调试工具(续)
gdb常用的调试命令 命令 file step next run quit print break shell 指定需要进行调试的程序 单步(行)执行,如果遇到函数会进入函数内部 单步( 执行, 单步( 单步(行)执行,如果遇到函数不会进入函数内部 执行, 启动被执行的程序 退出gdb调试环境 退出gdb调试环境 gdb 查看变量或者表达式的值 设置断点, 设置断点,程序执行到断点就会暂停起来 执行其后的shell命令 执行其后的shell命令 shell 含义
3. gdb程序调试工具(续)
控制程序的执行--设置断点
编译源程序时需要使用-g选项 在gdb中用break命令(其缩写形式为b)设置断点:
(在当前文件指定行linenum处设置断点,停在该行开头) ● break linenu
m if condition (在当前文件指定行linenum处设置断点,但 仅在条件表达式condition成立时才停止程序执行) ● break function (在当前文件函数function的入口处设置断点) ● break file:linenum (在源文件file的linenum行上设置断点) (在源文件file的函数function的入口处设置断点) ● break file:function ● break *address (运行程序在指定的内存地址address处停止) ● break (不带任何参数,则表示在下一条指令处停止)
● break linenum
断点应设置在可执行的行上,不应是变量定义之类的语句。
3. gdb程序调试工具(续)
2. 显示断点
info breakpoints [num] info break [num]
3.删除断点
delete [bkptnums]
4.运行程序
run [args] (run简写是r)
5.程序的单步跟踪和连续执行
(1)单步跟踪
step [N] 参数N表示每步执行的语句行数。 进入被调用函数内部执行。 next [N] 参数N表示每步执行的语句行数。 被调用函数被当做一条指令执行。 stepi(缩写为si)或nexti(缩写为ni)命令一条一条地执行机器指令。
(2)连续执行
利用continue,c或fg命令连续执行到下一个断点 。
3. gdb程序调试工具(续)
6.函数调用
call expr 其中,expr是所用编程语言的函数调用表达式,包括函数名和实参。 在调试过程中,可以使用return命令强行从正在执行的函数中退出:
return [expr]
还可以使用finish命令退出函数,但它并不立即退出,而是继续运行, 直至当前函数返回。
调试举例
greeting.h #ifndef _GREETING_H #define _GREETING_H void greeting (char * name); #endif greeting.c #include #include "greeting.h" void greeting (char * name) { printf("Hello !\r\n"); } my_app.c 1 #include 2 #include "greeting.h" 3 #define N 10 4 int main(void) 5 { 6 char name[n]; 7 printf("Your Name,Please:"); 8 scanf("%s",name) 9 greeting(name); 10 /*return 0;*/ 11 }
源文件
分块编译
greeting.c
静态调试举例
$gcc -g -Wall -c functions/greeting.c
-g:将调试信息加入到编译的目标文件中 ; -Wall:将编译过程中的所有级别的警告都打印出来 ;
无错误
my_app.c
$gcc -g -Wall -c my_app.c -Ifunctions 参数含义同上 错误信息:
静态调试举例
错误信息:
my_app.c: In function `main': my_app.c:6: `n' undeclared (first use in this function) my_app.c:6: (Each undeclared identifier is reported only once my_app.c:6: for each function it appears in.) my_app.c:9: parse error before "greeting" my_app.c:6: warning: unused variable `name'
错误记录格式:
文件名:行好:错误描述
静态调试举例
分析、定位错误(警告):
my_app.c的第6行:
描述含义:
n是一个没有声明的变量;
分析
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论