C编译c 程序反编译是?

编译简单的&C&程序 C&语言经典的入门例子是&Hello&World,下面是一示例代码: #include&&stdio.h&&
int&main(void)&
{ &&&&printf("Hello,&world!\n");&&&&&
return&0;&
} 我们假定该代码存为文件&hello.c&。要用&gcc&编译该文件,使用下面的命令: $&gcc&-g&-Wall&hello.c&-o&hello 该命令将文件&hello.c&中的代码编译为机器码并存储在可执行文件&&hello&中。机器码的文件名是通过&-o&选项指定的。该选项通常作为命令行中的最后一个参数。如果被省略,输出文件默认为&&a.out&。 注意到如果当前目录中与可执行文件重名的文件已经存在,它将被覆盖。 选项&-Wall&开启编译器几乎所有常用的警告──强烈建议你始终使用该选项。编译器有很多其他的警告选项,但&-Wall&是最常用的。默认情况下GCC&不会产生任何警告信息。当编写&C&或&C++&程序时编译器警告非常有助于检测程序存在的问题。&注意如果有用到math.h库等非gcc默认调用的标准库,请使用-lm参数 本例中,编译器使用了&-Wall&选项而没产生任何警告,因为示例程序是完全合法的。&选项&""-g""&表示在生成的目标文件中带调试信息,调试信息可以在程序异常中止产生core后,帮助分析错误产生的源头,包括产生错误的文件名和行号等非常多有用的信息。&要运行该程序,输入可执行文件的路径如下: $&./hello Hello,&world! 这将可执行文件载入内存,并使&CPU&开始执行其包含的指令。&路径&./&指代当前目录,因此&./hello&载入并执行当前目录下的可执行文件&&hello&。&点击此处下载本节的操作视频 捕捉错误 如上所述,当用&C&或&C++&编程时,编译器警告是非常重要的助手。为了说明这一点,下面的例子包含一个微妙的错误:为一个整数值错误地指定了一浮点数控制符&%f&。 #include&&stdio.h&&& int&main&(void)&
{ &&&&printf&("Two&plus&two&is&%f\n",&4);&&&&&
&&& return&0;&
} 一眼看去该错误并不明显,但是它可被编译器捕捉到,只要启用了警告选项&-Wall。&编译上面的程序&bad.c&,将得到如下的消息: $&gcc&-Wall&-o&bad&bad.c&
main.c:&在函数&main&中: main.c:5:&警告:&格式&%f&需要类型&double&,但实参&2&的类型为&int& &这表明文件&&bad.c&第&6&行中的格式字符串用法不正确。GCC&的消息总是具有下面的格式&文件名:行号:消息。编译器对错误与警告区别对待,前者将阻止编译,后者表明可能存在的问题但并不阻止程序编译。 本例中,对整数值来说,正确的格式控制符应该是&%d。 如果不启用&-Wall,程序表面看起来编译正常,但是会产生不正确的结果: $&gcc&bad.c&-o&bad&
$&./bad Two&plus&two&is&0.000000 显而易见,开发程序时不检查警告是非常危险的。如果有函数使用不当,将可能导致程序崩溃或产生错误的结果。开启编译器警告选项&-Wall&可捕捉&C&编程时的多数常见错误。
编译多个源文件 一个源程序可以分成几个文件。这样便于编辑与理解,尤其是程序非常大的时候。这也使各部分独立编译成为可能。 下面的例子中我们将程序&Hello&World&分割成&3&个文件:&hello.c&,&hello_fn.c&和头文件&hello.h&。
这是主程序&hello.c&: #include&"hello.h"&
int&main(void)&
{ &&&&hello&("world");&&&&&
&&& return&0;&
} 在先前例子的&hello.c&中,我们调用的是库函数&printf,本例中我们用一个定义在文件&hello_fn.c&中的函数&hello&取代它。 主程序中包含有头文件&hello.h&,该头文件包含函数&hello&的声明。我们不需要在&hello.c&文件中包含系统头文件&stdio.h&来声明函数&printf,因为&hello.c&没有直接调用&printf。
文件&hello.h&中的声明只用了一行就指定了函数&hello&的原型。 void&hello&(const&char&*&name);
函数&hello&的定义在文件&hello_fn.c&中: #include&&stdio.h&&
#include&"hello.h"&& void&hello&(const&char&*&name)&
{ &&&&printf&("Hello,&%s!\n",&name);&
} 语句&#include&"FILE.h"&与&#include&&FILE.h&&有所不同:前者在搜索系统头文件目录之前将先在当前目录中搜索文件&FILE.h&,后者只搜索系统头文件而不查看当前目录。&要用gcc编译以上源文件,使用下面的命令: $&gcc&-Wall&hello.c&hello_fn.c&-o&newhello 本例中,我们使用选项&-o&为可执行文件指定了一个不同的名字&newhello。注意到头文件&hello.h&并未在命令行中指定。源文件中的的&#include&"hello.h"&指示符使得编译器自动将其包含到合适的位置。 要运行本程序,输入可执行文件的路径名: $&./newhello&
Hello,&world! 源程序各部分被编译为单一的可执行文件,它与我们先前的例子产生的结果相同。
---------------------------------------
undefined reference to `sqrt' 问题
在gcc下用到数学函数,如sqrt。在gcc时要加上&-lm&参数,这样告诉编译器我要用到数学函数了 。
a.c -o a -lm
阅读(...) 评论()您所在的位置: &
C程序编译和链接
C程序编译和链接
机械工业出版社
《Linux内核完全剖析―基于0.12内核》第3章内核编程语言和环境,本章主要描述Linux 0.12内核中使用的编程语言、目标文件格式和编译环境,主要目标是提供阅读Linux 0.12内核源代码所需要的汇编语言和GNU C语言扩展知识。本节为大家介绍的是C程序编译和链接。
3.3& C语言程序
GNU gcc对ISO标准C89描述的C语言进行了一些扩展,其中一些扩展部分已经包括进ISO C99标准中。本节给出内核中经常用到的一些gcc扩充语句的说明。在后面章节的程序注释中也会随时对遇到的扩展语句给出简单的说明。
3.3.1& C程序编译和链接
使用gcc汇编器编译C语言程序时通常会经过4个处理阶段,即预处理阶段、编译阶段、汇编阶段和链接阶段,如图3-3所示。
(点击查看大图)图3-3& C程序编译过程
在预处理阶段中,gcc会把C程序传递给C前处理器cpp,对C语言程序中指示符和宏进行替换处理,输出纯C语言代码;在编译阶段,gcc把C语言程序编译生成对应的与机器相关的as汇编语言代码;在汇编阶段,as汇编器会把汇编代码转换成机器指令,并以特定二进制格式输出保存在目标文件中;最后GNU ld链接器把程序的相关目标文件组合链接在一起,生成程序的可执行映像文件。调用gcc的命令行格式与编译汇编语言的格式类似:
gcc [ 选项 ] [ -o outfile ] infile ...
其中infile是输入的C语言文件;outfile是编译产生的输出文件。
对于某次编译过程,并非一定要全部执行这4个阶段,使用命令行选项可以令gcc编译过程在某个处理阶段后就停止执行。例如,使用"-S"选项可以让gcc在输出了C程序对应的汇编语言程序之后就停止运行;使用"-c"选项可以让gcc只生成目标文件而不执行链接处理,如下所示。
gcc -o hello hello.c& &// 编译hello.c程序,生成执行文件hello。gcc -S -o hello.s hello.c &// 编译hello.c程序,生成对应汇编程序hello.s。gcc -c -o hello.o hello.c&// 编译hello.c程序,生成对应目标文件hello.o而不链接。
在编译像Linux 内核这样的包含很多源程序文件的大型程序时,通常使用make工具软件对整个程序的编译过程进行自动管理,详见后面说明。【责任编辑: TEL:(010)】&&&&&&
关于&&&&&&的更多文章
周一是“双十一”,为这美好的一周打响了头炮,自然好事也接踵而
本书描述了黑客用默默无闻的行动为数字世界照亮了一条道路的故事。
本书定位很明确,内容有趣易懂。本书不同于大多数"伪
电商圈第一本自媒体著作《做自己--鬼脚七自媒体第一季
中国对冲基金经理风云录是对冲网阿尔法研究中心组编的
本书全面、深入地介绍了网络应用技术,主要内容包括:RMS权限管理服务、Exchange邮件服务、LCS即时消息服务、WSUS系统更新服务、
51CTO旗下网站C++条件编译实现方法
C++条件编译实现方法
  你所遇到的这几个宏是为了进行条件编译。一般情况下,源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。 &&&&&条件编译命令最常见的形式为: &&&&#ifdef&标识符& &&&&程序段1& &&&&#else& &&&&程序段2& &&&&#endif &&&& &&&&&它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。 &&&&&其中#else部分也可以没有,即: &&&&#ifdef& &&&&程序段1& &&&&#endif &&&& &&&&&这里的“程序段”可以是语句组,也可以是命令行。这种条件编译可以提高C源程序的通用性。如果一个C源程序在不同计算机系统上系统上运行,而不同的计算机又有一定的差异。例如,我们有一个数据类型,在Windows平台中,应该使用long类型表示,而在其他平台应该使用float表示,这样往往需要对源程序作必要的修改,这就降低了程序的通用性。可以用以下的条件编译: &&&&#ifdef&WINDOWS& &&&&#define&MYTYPE&long& &&&&#else& &&&&#define&MYTYPE&float& &&&&#endif &&&& &&&&&如果在Windows上编译程序,则可以在程序的开始加上 &&&&#define&WINDOWS &&&& &&&&&这样则编译下面的命令行: &&&&#define&MYTYPE&long &&&& &&&&&如果在这组条件编译命令之前曾出现以下命令行: &&&&#define&WINDOWS&0 &&&& &&&&&则预编译后程序中的MYTYPE都用float代替。这样,源程序可以不必作任何修改就可以用于不同类型的计算机系统。当然以上介绍的只是一种简单的情况,可以根据此思路设计出其它的条件编译。 &&&&&例如,在调试程序时,常常希望输出一些所需的信息,而在调试完成后不再输出这些信息。可以在源程序中插入以下的条件编译段: &&&&#ifdef&DEBUG& &&&&print&(\"device_open(%p)\\n\",&file);& &&&&#endif &&&& &&&&&如果在它的前面有以下命令行: &&&&#define&DEBUG &&&& &&&&&则在程序运行时输出file指针的值,以便调试分析。调试完成后只需将这个define命令行删除即可。有人可能觉得不用条件编译也可达此目的,即在调试时加一批printf语句,调试后一一将printf语句删除去。的确,这是可以的。但是,当调试时加的printf语句比较多时,修改的工作量是很大的。用条件编译,则不必一一删改printf语句,只需删除前面的一条“#define&DEBUG”命令即可,这时所有的用DEBUG作标识符的条件编译段都使其中的printf语句不起作用,即起统一控制的作用,如同一个“开关”一样。 [Page]&&&&&有时也采用下面的形式: &&&&#ifndef&标识符& &&&&程序段1& &&&&#else& &&&&程序段2& &&&&#endif &&&& &&&&&只是第一行与第一种形式不同:将“ifdef”改为“ifndef”。它的作用是:若标识符未被定义则编译程序段1,否则编译程序段2。这种形式与第一种形式的作用相反。 &&&&&以上两种形式用法差不多,根据需要任选一种,视方便而定。 &&&&&还有一种形式,就是#if后面的是一个表达式,而不是一个简单的标识符: &&&&#if&表达式& &&&&程序段1& &&&&#else& &&&&程序段2& &&&&#endif &&&& &&&&&它的作用是:当指定的表达式值为真(非零)时就编译程序段1,否则编译程序段2。可以事先给定一定条件,使程序在不同的条件下执行不同的功能。 &&&&&例如:输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或全改为小写字母输出。 &&&&#define&LETTER&1& &&&&main()& &&&&{& &&&&char&str[20]=\"C&Language\",c;& &&&&int&i=0;& &&&&while((c=str[i])!=’\\0’){& &&&&i++;& &&&&#if&LETTER& &&&&if(c&=’a’&&c&=’z’)&c=\"c-32\";& &&&&#else& &&&&if(c&=’A’&&c&=’Z’)&c=\"c\"+32;& &&&&#endif&
  [NextPage]
  printf(\"%c\",c);& &&&&}& &&&&} &&&& &&&&&运行结果为:C&LANGUAGE &&&&&现在先定义LETTER为1,这样在预处理条件编译命令时,由于LETTER为真(非零),则对第一个if语句进行编译,运行时使小写字母变大写。如果将程序第一行改为: &&&&#define&LETTER&0 &&&& &&&&&则在预处理时,对第二个if语句进行编译处理,使大写字母变成小写字母(大写字母与相应的小写字母的ASCII代码差32)。此时运行情况为: &&&&&c&language &&&&&有人会问:不用条件编译命令而直接用if语句也能达到要求,用条件编译命令有什么好处呢?的确,此问题完全可以不用条件编译处理,但那样做目标程序长(因为所有语句都编译),而采用条件编译,可以减少被编译的语句,从而减少目标的长度。当条件编译段比较多时,目标程序长度可以大大减少。 [Page]文件中的#ifndef& 头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。 还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的: #ifndef&&标识& :}G\"{d}Guest#define&&标识& ...... }!Dg+t0il4rGuest...... #endif &标识&在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h #ifndef&_STDIO_H_ y6NW5GesGuest#define&_STDIO_H_ ...... #endif 2.在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。 #ifndef&AAAEETOP专业博客---电子工程师自己的家园+_8RY&W)@&OC8WH #define&AAA :G{#d:i)J-Ep&XGuest... )Ahzo&N8`B9YGuestint&i;EETOP专业博客---电子工程师自己的家园_;^T&usl ...EETOP专业博客---电子工程师自己的家园S&t0L$\\]REm9? #endif 0o3u_s2kz7h0V8G[CsGuest里面有一个变量定义 +c%G~,n?ZlGuest在vc中链接时就出现了i重复定义的错误,而在c中成功编译。 结论: (1).当你第一个使用这个头的.cpp文件生成.obj的时候,int&i&在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候,int&i&又被定义然后两个obj被另外一个.cpp也include&这个头的,连接在一起,就会出现重复定义. (2).把源程序文件扩展名改成.c后,VC按照C语言的语法对源程序进行编译,而不是C++。在C语言中,若是遇到多个int&i,则自动认为其中一个是定义,其他的是声明。 (3).C语言和C++语言连接结果不同,可能(猜测)时在进行编译的时候,C++语言将全局 RFX’r/G\"JrGuest变量默认为强符号,所以连接出错。C语言则依照是否初始化进行强弱的判断的。(参考) 解决方法: (1).把源程序文件扩展名改成.c。 (2).推荐解决方案: 5k[&En&E4RGuest.h中只声明&extern&int&i;在.cpp中定义 &x.h&EETOP专业博客---电子工程师自己的家园&x3l~&^|BP #ifndef&__X_H__EETOP专业博客---电子工程师自己的家园Nv9H#\\Y._A:GL+Q&XI #define&__X_H__EETOP专业博客---电子工程师自己的家园}9\\3x7Ik9xIKnW extern&int&i;EETOP专业博客---电子工程师自己的家园1}UxW(z&M&}1d&o #endif&//__X_H__ zGe&b*ExmGuest&x.c& ixc:t$X&zGuestint&i; 注意问题: (1).变量一般不要定义在.h文件中。 一般情况下,源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。 X1g2J&QV3|+QnGuest条件编译命令最常见的形式为:&EETOP专业博客---电子工程师自己的家园7e&n7w[]8G3[ [Page]&&&&&#ifdef&标识符 }$?*xz&TR?[JGuest&&&&&程序段1&EETOP专业博客---电子工程师自己的家园^t6D_&BJ &&&&&#else X(|XDv&G(@,SfGuest&&&&&程序段2&EETOP专业博客---电子工程师自己的家园.M%~:Yke1|Z;K8Q &&&&&#endif&EETOP专业博客---电子工程师自己的家园1?%m%I@q5Y &&&& BC6dG6I(OGuest&&&&&它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。&EETOP专业博客---电子工程师自己的家园9?2[tx8EKZ &&&&&其中#else部分也可以没有,即:&EETOP专业博客---电子工程师自己的家园K%L#Z&@h,Op[)Rn &&&&&#ifdef q-A#G6sd%TGuest&&&&&程序段1 o*X1l6aa1mGuest&&&&&#denif&EETOP专业博客---电子工程师自己的家园{X)u+n3_A &&&&&EETOP专业博客---电子工程师自己的家园&y|.@KNS%\\tS &&&&&这里的“程序段”可以是语句组,也可以是命令行。这种条件编译可以提高C源程序的通用性。如果一个C源程序在不同计算机系统上系统上运行,而不同的计算机又有一定的差异。例如,我们有一个数据类型,在Windows平台中,应该使用long类型表示,而在其他平台应该使用float表示,这样往往需要对源程序作必要的修改,这就降低了程序的通用性。可以用以下的条件编译:
  [NextPage]
  Oo0?(^b’suGuest&&&&&#ifdef&WINDOWS K[{1C%CD.U.i4OGuest&&&&&#define&MYTYPE&long&EETOP专业博客---电子工程师自己的家园&X-|#f2u*D+j&}xG &&&&&#else&EETOP专业博客---电子工程师自己的家园8c\"Y/[$n!QVb &&&&&#define&MYTYPE&float H’Q/N@4vGuest&&&&&#endif&EETOP专业博客---电子工程师自己的家园;p6`jd3OP0Se8V &&&& ?JTIn’AYoGuest&&&&&如果在Windows上编译程序,则可以在程序的开始加上 0HOpZ0CH)hBGuest&&&&&#define&WINDOWS Kj;qXO&v8ykGuest&&&&&EETOP专业博客---电子工程师自己的家园&ey&J$r,U &&&&&这样则编译下面的命令行:&EETOP专业博客---电子工程师自己的家园uK&Amkx &&&&&#define&MYTYPE&long&EETOP专业博客---电子工程师自己的家园bS3_)zREYv+l*? &&&&&EETOP专业博客---电子工程师自己的家园&cUe^.QCp;e &&&&&如果在这组条件编译命令之前曾出现以下命令行:&EETOP专业博客---电子工程师自己的家园!Rb~n9Y&gA\"x+jB6\\&L [Page]&&&&&#define&WINDOWS&0&EETOP专业博客---电子工程师自己的家园?&f%hS#xsP &&&&&EETOP专业博客---电子工程师自己的家园1I%O\"HA.q&}/e%? &&&&&则预编译后程序中的MYTYPE都用float代替。这样,源程序可以不必作任何修改就可以用于不同类型的计算机系统。当然以上介绍的只是一种简单的情况,可以根据此思路设瞥?a&href=\"javascript:;\"&onClick=\"tagshow(event,&’%C6%E4%CB%FC’);return&\"&其它的条件编译? tRX1w9G&a{0{AGuest&&&&&例如,在调试程序时,常常希望输出一些所需的信息,而在调试完成后不再输出这些信息。可以在源程序中插入以下的条件编译段:&EETOP专业博客---电子工程师自己的家园GRd*IR &&&&&#ifdef&DEBUG )k[?^7LGuest&&&&&print&(\"device_open(%p)&\",&file);&EETOP专业博客---电子工程师自己的家园:k*P.U}\"d#YdZ9[ &&&&&#endif 4LoC3DDn.]Guest&&&& j\"Q5`&q{Guest&&&&&如果在它的前面有以下命令行:&EETOP专业博客---电子工程师自己的家园)t!Z1g~U4h3@$z &&&&&#define&DEBUG by#K&y*nz9g0TyvGuest&&&&&EETOP专业博客---电子工程师自己的家园wJu:h)a,q&^&Q &&&&&则在程序运行时输出file指针的值,以便调试分析。调试完成后只需将这个define命令行删除即可。有人可能觉得不用条件编译也可达此目的,即在调试时加一批printf语句,调试后一一将printf语句删除去。的确,这是可以的。但是,当调试时加的printf语句比较多时,修改的工作量是很大的。用条件编译,则不必一一删改printf语句,只需删除前面的一条“#define&DEBUG”命令即可,这时所有的用DEBUG作标识符的条件编译段都使其中的printf语句不起作用,即起统一控制的作用,如同一个“开关”一样。&EETOP专业博客---电子工程师自己的家园0F4D@1PK(LGcI+L8C &&&&&有时也采用下面的形式: l#U.@y8p*Wnw!NY&jGuest&&&&&#ifndef&标识符&EETOP专业博客---电子工程师自己的家园1Z)?3X&hV&j~ &&&&&程序段1 {z&DX/kGuest&&&&&#else&EETOP专业博客---电子工程师自己的家园Sov@-J&NV &&&&&程序段2&EETOP专业博客---电子工程师自己的家园9b(~&]GM&} &&&&&#endif&EETOP专业博客---电子工程师自己的家园*_%I`X,Rv\\6x &&&&&EETOP专业博客---电子工程师自己的家园:I9yU[B &&&&&只是第一行与第一种形式不同:将“ifdef”改为“ifndef”。它的作用是:若标识符未被定义则编译程序段1,否则编译程序段2。这种形式与第一种形式的作用相反。&EETOP专业博客---电子工程师自己的家园+z9f},mL:Z}P [Page]&&&&&以上两种形式用法差不多,根据需要任选一种,视方便而定。&EETOP专业博客---电子工程师自己的家园F&S0@3v&_ &&&&&还有一种形式,就是#if后面的是一个表达式,而不是一个简单的标识符: 4^$w+J&Vd#\\mGuest&&&&&#if&表达式&EETOP专业博客---电子工程师自己的家园.]-l,^]Y &&&&&程序段1&EETOP专业博客---电子工程师自己的家园)}IlI:B&K)C &&&&&#else &[(a$h/Q#CP,mnqGuest&&&&&程序段2&EETOP专业博客---电子工程师自己的家园%UJcX4[5D &&&&&#endif&EETOP专业博客---电子工程师自己的家园(Ll/ydH1l&bJG&r &&&&&EETOP专业博客---电子工程师自己的家园&?&S0Wlb\\ &&&&&它的作用是:当指定的表达式值为真(非零)时就编译程序段1,否则编译程序段2。可以事先给定一定条件,使程序在不同的条件下执行不同的功能。 作用范围就是当前文件啊。因为编译是以cpp或c文件位单位的嘛。还以这个为例:
  [NextPage]
  //正常代码EETOP专业博客---电子工程师自己的家园C&Y_W&].Tu3O:V;A #ifdef&_DEBUG .F,`\"CclGuest&&&&&&TRACE(\"Some&infomation\");EETOP专业博客---电子工程师自己的家园+f/Z&^3g-Y~{/~Fg^ #elseEETOP专业博客---电子工程师自己的家园(RLkS2p0frb &&&&&&//Now&is&release&version,so&do&nothing Q2{ht3G&S5`5_G.|Guest#endifEETOP专业博客---电子工程师自己的家园?MY(U/bI&da/N //正常代码 编译时是先把所有的预编译处理展开(比如宏)再编译,所以Debug模式下,编译时的代码是:EETOP专业博客---电子工程师自己的家园’F-Sv(B/O.M7B)J //正常代码EETOP专业博客---电子工程师自己的家园m(T/Of)E8XT$]O’@ TRACE(\"Some&infomation\"); kh|L&at|Guest//正常代码 Release模式下的代码是:EETOP专业博客---电子工程师自己的家园d(s8?2Os{&f-m9A //正常代码EETOP专业博客---电子工程师自己的家园u%xpN?bg}5{[ //正常代码 预处理就是在进行编译的第一遍词法扫描和语法分析之前所作的工作。说白了,就是对源文件进行编译前,先对预处理部分进行处理,然后对处理后的代码进行编译。这样做的好处是,经过处理后的代码,将会变的很精短。 &&&关于预处理命令中的文件包含(#include),宏定义(#define),书上已经有了详细的说明,在这里就不详述了。这里主要是对条件编译(#ifdef,#else,#endif,#if等)进行说明。以下分3种情况:& 1:情况1: #ifdef&_XXXX ...程序段1... #else ...程序段2... #endif &&&这表明如果标识符_XXXX已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。 例:& [Page]#define&NUM ............. ............. ............. #ifdef&NUM &&&printf(\"之前NUM有过定义啦!:)&\\n\"); #else &&&printf(\"之前NUM没有过定义!:(&\\n\"); #endif } &&&如果程序开头有#define&NUM这行,即NUM有定义,碰到下面#ifdef&NUM的时候,当然执行第一个printf。否则第二个printf将被执行。 &&&我认为,用这种,可以很方便的开启/关闭整个程序的某项特定功能。 2:情况2:& #ifndef&_XXXX& ...程序段1...& #else& ...程序段2...& #endif &&&这里使用了#ifndef,表示的是if&not&def。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。例子就不举了。 3:情况3: #if&常量& ...程序段1... #else ...程序段2... #endif& &&&这里表示,如果常量为真(非0,随便什么数字,只要不是0),就执行程序段1,否则执行程序段2。 &&&我认为,这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1就好了。而不要测试的时候,只要将常量变0。 #if语句要判断是宏的值,宏的值只有通过#define或者在命令行-DXXX的形式定义。 用const&int&UP&=&1;形式定义了一个整型常量,而不是一个宏。 对于宏的替换,是在预编译阶段就进行的,会把所有的宏替换为实际的值。而对const&int&UP的解析,却是在编译阶段。 在预编译阶段,只认#define定义的宏,不会理会const&int&定义出来的常量,所以#if永远为假。 【fallinleave】: #if寻找UP宏,你用const只是定义常量,并没有UP这个宏,而#define&是定义的宏,所以成立。
&&&主编推荐
H3C认证Java认证Oracle认证
基础英语软考英语项目管理英语职场英语
.NETPowerBuilderWeb开发游戏开发Perl
二级模拟试题一级模拟试题一级考试经验四级考试资料
港口与航道工程建设工程法规及相关知识建设工程经济考试大纲矿业工程市政公用工程通信与广电工程
操作系统汇编语言计算机系统结构人工智能数据库系统微机与接口
软件测试软件外包系统分析与建模敏捷开发
法律法规历年试题软考英语网络管理员系统架构设计师信息系统监理师
高级通信工程师考试大纲设备环境综合能力
路由技术网络存储无线网络网络设备
CPMP考试prince2认证项目范围管理项目配置管理项目管理案例项目经理项目干系人管理
Powerpoint教程WPS教程
电子政务客户关系管理首席信息官办公自动化大数据
职称考试题目
就业指导签约违约职业测评
招生信息考研政治
网络安全安全设置工具使用手机安全
3DMax教程Flash教程CorelDraw教程Director教程
Dreamwaver教程HTML教程网站策划网站运营Frontpage教程
生物识别传感器物联网传输层物联网前沿技术物联网案例分析
互联网电信IT业界IT生活
Java核心技术J2ME教程
Linux系统管理Linux编程Linux安全AIX教程
Windows系统管理Windows教程Windows网络管理Windows故障
组织运营财务资本
视频播放文件压缩杀毒软件输入法微博
数据库开发Sybase数据库Informix数据库
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&&&湘教QS2-164&&增值电信业务经营许可证湘B2-

我要回帖

更多关于 linux下编译c程序 的文章

 

随机推荐