精华内容
下载资源
问答
  • 问关于C语言预处理命令 答 我们可以在C 源程序中插入传给 编译程序各种指令这些指令被称为预处理器指令等价于汇编语言中伪指令它们扩充了程序设计的环境 现把常用 预处理命令总结如下 1. 预处理程序 按照...
  • 问关于 C 语言中预处理命令 答 我们可以在 C 源程序 中插入传给 编译程序 各种指令这些指令被称为 预处理器指令等价于 汇编语言中伪指令 它们扩充了程序设计的环境 现把常用 预处理命令 总结如下 预处理程序...
  • 问关于 C 语言中预处理命令 答 我们可以在 C 源程序 中插入传给 编译程序 各种指令这些指令被称为 预处理器指令等价于 汇编语言中伪指令 它们扩充了程序设计的环境 现把常用 预处理命令 总结如下 1....
  • 第一章 Linux 基础2学时 实验一 LINUX编程环境 实验目的 熟悉Linux下C语言程序设计基本步骤 掌握gcc编译器各种参数使用方法 掌握gcc编译器创建函数库方法 掌握gdb调试程序方法 掌握多文件编译makefile...
  • c语言和JavaScript在语法结构上很多相似(例如if条件语句、while循环、switch语句、do-while循环等),那么它们之间什么不同?...C语言是仅产生少量机器语言以及不需要任何运行环境支持便能运行...

    c语言和JavaScript在语法结构上有很多相似(例如if条件语句、while循环、switch语句、do-while循环等),那么它们之间有什么不同?下面本篇文章就来给大家介绍一下c语言和JavaScript。

    dfb9f33bfe7db7622dcd6cc602252e47.png

    什么是C语言?

    C语言是一门面向过程、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。

    尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括一些类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。

    什么是JavaScript?

    JavaScript是一种高级的、解释型、直译式脚本语言,是一种基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。

    JavaScript已经由ECMA(欧洲计算机制造商协会)通过ECMAScript实现语言的标准化。它被世界上的绝大多数网站所使用,也被世界主流浏览器(Chrome、IE、Firefox、Safari、Opera)支持。

    JavaScript是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。

    C语言和JavaScript的区别:

    1、C语言主要是被编译成机器语言,而JavaScript主要是作为脚本被解释器解释执行;

    2、C语言需要程序员手动管理内存(主要指堆内存的申请和释放),而JavaScript的内存是由解释器来管理的;

    3、C语言是静态类型语言,即程序运行之前每个变量的数据类型就已经确定,在运行时不能改变,而JavaScript是动态类型语言,变量的数据类型在运行时仍可变化;

    4、C语言中没有闭包的概念,JavaScript中的函数都与其定义时可访问到的变量组成闭包;

    5、C语言没有对“类的成员方法”“类的成员的封装(对外不可见)”“类的继承与多态”等面向对象的特性的支持,而JavaScript可以通过原型链和闭包等实现面向对象的继承、多态和封装,实现ECMAScript 2015及以上版本的JavaScript更是在语法层面支持类的定义;

    6、C语言可以通过调用系统API来实现多线程,可以通过多线程来提高阻塞操作(主要是IO)时的CPU利用率,而JavaScript主要是单线程,JavaScript的可能阻塞的操作都由JavaScript运行时提供的异步API来完成

    展开全文
  • C语言的编译器常见的有哪些

    千次阅读 2019-04-19 20:47:06
    1、 visual c++6.0 (常见就是学校机房...3、 TCC非常方便:大小只有几M,但是编译时麻烦; 4、 Code::Blocks(win7、8都可以用); 5、 gcc:可以和Notepad++搭配,安装需要考虑环境配置问题; 6、C-Free 等等 ...

    1、 visual c++6.0 (常见的就是学校机房安装) ;
    2、 visual studio (很好用,很多人选择安装) ;
    3、 TCC非常方便:大小只有几M,但是编译时麻烦;
    4、 Code::Blocks(win7、8都可以用);
    5、 gcc:可以和Notepad++搭配,安装需要考虑环境配置问题;
    6、C-Free 等等

    展开全文
  • C语言编译过程详解

    2013-03-31 02:10:00
    他在一些技术群里问到:在windows下有哪些免费开源开发环境,我只到CooCox和ARM-GCC,我就建议使用CooCox,因为CooCox有CoIDE,是一个集成开发环境,比ARM-GCC容易上手。他那是还不知道CooCox,他就加我好友,...

          这几天,认识以为网友,qq名叫江湖人。这个人挺有想法的,在自己业余时间干自己喜欢做的事情,喜欢电子,承接企业项目业余创业。他在一些技术群里问到:在windows下有哪些免费开源的开发环境,我只到CooCox和ARM-GCC,我就建议使用CooCox,因为CooCox有CoIDE,是一个集成的开发环境,比ARM-GCC容易上手。他那是还不知道CooCox,他就加我好友,后来了解到,他是想自己做一个IDE,现在要做的就是要先架构一个ARM工程的编译环境,使用cdm命令进行编译连接。我马上就建议使用ARM-GCC,自己搭一个开发环境。他不懂,就要我帮他做好然后告诉他方法。我表示亚历山大啊,我只有在Linux下使用过gcc。现在要我直接去搭一个基于windows下的gcc编译环境, 肯定是不能一下子完成的。我自己也想去尝试下,多学一点肯定对自己的发展是有好处的。我就答应下来帮他,几天过去,一直也没去搞这事,一来是自己要去忙自己的项目,二来我女朋友来看我了,瞎玩了一段时间,这事就耽搁下来了。今天晚上,我问他问题解决了没有,他说他打算用CooCox里面的IDE了,我猜他选择CoIDE是因为CooCox也是免费开源的吧,在开发项目上没有版权争端吧。他还说到一个问题:怎么生成静态链接库?他在尝试着使用自己写几个.C文件,然后编译成以lib开头的.a静态编译文件,然后在编译成可执行文件HEX,编译成功,但是生成的HEX文件大小为零。我也不知道是什么原因,菜鸟的水平就是让人无法忍受啊。想去帮人解决问题,水平太低帮不了,这是一件何等难受的事情。我就做了终生学习的决心,坚持把握好每一天的一分一秒,集中精力学习嵌入式操作系统应用开发技术。好像是跑题了,呵呵,回过来讲生成静态链接库的问题,这个是编译原理的知识,我现在大三,没学编译原理,后面肯定也不会开这个课,所以我打算后面自学这个内容。下面是我今天晚上到网上找到的有关C语言编译连接最后生成可执行程序的介绍,算是一个入门级的一个总结吧。

      C语言的编译链接过程是要把我们编写的一个C程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织形成最终生成可执行代码的过程。过程图解如下:
           
    从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。
    一、编译过程
    编译过程又可以分成两个阶段:编译和汇编。
    1、编译
    编译是读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,源文件的编译过程包含两个主要阶段:
    第一个阶段是预处理阶段,在正式的编译阶段之前进行。预处理阶段将根据已放置在文件中的预处理指令来修改源文件的内容。如#include指令就是一个预处理指令,它把头文件的内容添加到.cpp文件中。这个在编译之前修改源文件的方式提供了很大的灵活性,以适应不同的计算机和操作系统环境的限制。一个环境需要的代码跟另一个环境所需的代码可能有所不同,因为可用的硬件或操作系统是不同的。在许多情况下,可以把用于不同环境的代码放在同一个文件中,再在预处理阶段修改代码,使之适应当前的环境。
    主要是以下几方面的处理:
    (1)宏定义指令,如 #define a   b。
    对于这种伪指令,预编译所要做的是将程序中的所有a用b替换,但作为字符串常量的 a则不被替换。还有 #undef,则将取消对某个宏的定义,使以后该串的出现不再被替换。
    (2)条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等。
    这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉
    (3) 头文件包含指令,如#include "FileName"或者#include <FileName>等。
    在头文件中一般用伪指令#define定义了大量的宏(最常见的是字符常量),同时包含有各种外部符号的声明。采用头文件的目的主要是为了使某些定义可以供多个不同的C源程序使用。因为在需要用到这些定义的C源程序中,只需加上一条#include语句即可,而不必再在此文件中将这些定义重复一遍。预编译程序将把头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。包含到C源程序中的头文件可以是系统提供的,这些头文件一般被放在/usr/include目录下。在程序中#include它们要使用尖括号(<>)。另外开发人员也可以定义自己的头文件,这些文件一般与C源程序放在同一目录下,此时在#include中要用双引号("")。
    (4)特殊符号,预编译程序可以识别一些特殊的符号。
    例如在源程序中出现的LINE标识将被解释为当前行号(十进制数),FILE则被解释为当前被编译的C源程序的名称。预编译程序对于在源程序中出现的这些串将用合适的值进行替换。
    预编译程序所完成的基本上是对源程序的“替代”工作。经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同。下一步,此输出文件将作为编译程序的输出而被翻译成为机器指令。
    第二个阶段编译、优化阶段。经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义,以及C语言的关键字,如main,if,else,for,while,{,}, +,-,*,\等等。
    编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
    优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅同编译技术本身有关,而且同机器的硬件环境也有很大的关系。优化一部分是对中间代码的优化。这种优化不依赖于具体的计算机。另一种优化则主要针对目标代码的生成而进行的。
    对于前一种优化,主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制条件、已知量的合并等)、复写传播,以及无用赋值的删除,等等。
    后一种类型的优化同机器的硬件结构密切相关,最主要的是考虑是如何充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次数。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码比较短,执行的效率比较高,也是一个重要的研究课题。
    2、汇编
    汇编实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。目标文件由段组成。通常一个目标文件中至少有两个段:
    代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。
    数据段:主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。
    UNIX环境下主要有三种类型的目标文件:
    (1)可重定位文件
    其中包含有适合于其它目标文件链接来创建一个可执行的或者共享的目标文件的代码和数据。
    (2)共享的目标文件
    这种文件存放了适合于在两种上下文里链接的代码和数据。
    第一种是链接程序可把它与其它可重定位文件及共享的目标文件一起处理来创建另一个 目标文件;
    第二种是动态链接程序将它与另一个可执行文件及其它的共享目标文件结合到一起,创建一个进程映象。
    (3)可执行文件
    它包含了一个可以被操作系统创建一个进程来执行之的文件。汇编程序生成的实际上是第一种类型的目标文件。对于后两种还需要其他的一些处理方能得到,这个就是链接程序的工作了。
    二、链接过程
    由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。
    例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
    链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。
    根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
    (1)静态链接
    在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。
    (2) 动态链接
    在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。
    对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。
    我们在linux使用的gcc编译器便是把以上的几个过程进行捆绑,使用户只使用一次命令就把编译工作完成,这的确方便了编译工作,但对于初学者了解编译过程就很不利了,下图便是gcc代理的编译过程:

    从上图可以看到:
    预编译
    将.c 文件转化成 .i文件
    使用的gcc命令是:gcc –E
    对应于预处理命令cpp
    编译
    将.c/.h文件转换成.s文件
    使用的gcc命令是:gcc –S
    对应于编译命令 cc –S
    汇编
    将.s 文件转化成 .o文件
    使用的gcc 命令是:gcc –c
    对应于汇编命令是   as
    链接
    将.o文件转化成可执行程序
    使用的gcc 命令是: gcc
    对应于链接命令是   ld
    总结起来编译过程就上面的四个过程:预编译、编译、汇编、链接。了解这四个过程中所做的工作,对我们理解头文件、库等的工作过程是有帮助的,而且清楚的了解编译链接过程还对我们在编程时定位错误,以及编程时尽量调动编译器的检测错误会有很大的帮助的。

    转载于:https://www.cnblogs.com/Zero_Victor/archive/2013/03/31/2991227.html

    展开全文
  • 3:C语言的预处理操作都有哪些?宏定义和函数的主要区别在哪? 1、我们写的.c程序如何变为可执行程序?(.c到.exe) 废话不说,直接上图: 从图中我们可以看到.c文件到.exe文件之间主要存在预处理、编译、汇编...

    C语言-程序环境与预处理详解

    首先抛出几个问题:

    1:我们都知道电脑或其它硬件设备都只认识二进制数据,那么我们编写的.c文件如何被计算机所识别?

    2:写过C语言代码的都知道,如果程序中有错误,编译器会报错,那么错误主要有哪些?又是怎么被计算机发现的?

    3:C语言的预处理操作都有哪些?宏定义和函数的主要区别在哪?

    1、我们写的.c程序如何变为可执行程序?(.c.exe

    废话不说,直接上图:

    从图中我们可以看到.c文件到.exe文件之间主要存在预处理、编译、汇编和链接步骤。这里就这四个步骤再详细说明一下:

    1:预处理

    下文中专门针对预处理进行详细讲解,这里先不多说。

    2:编译

    编译环节主要是将各个.i文件进行语句分析及符号汇总。比如每行代码结尾没有加分号,或判断语句后没有将判断条件用括号括起来等。 如果有错,将直接报错。(如果程序中存在不符合C语言语法的问题,IDE都会在编译环节进行报错。并且这一环节会将C语言代码转化为汇编代码

    (IDE:集成开发环境。 IDE的工作包含预处理、编译、汇编、链接以及调试器,我们使用的Visual Studio就是一款IDE)。

    3:汇编

    汇编的主要工作是将汇编代码转化为二进制文件(到这一步,我们用文本阅读器打开test.o文件,就已经无法阅读了,显示乱码),并且汇编也会形成符号表。

    形成符号表:

    4:链接链接的作用是合并符号表即符号表的重定位。(我们一个工程中会有很多个.c文件,每一个.c文件都会独立经过预处理、编译和汇编环节,每个.c都会生成一个目标文件(目标文件中包含各自.c文件中的符号表),然后在链接环节,链接器将全部的目标文件和相关链接库进行链接,生成.exe)。

    如果程序中存在未定义的变量或函数,或者在某一个.c中调用其它文件中的变量或函数 但没有包含头文件,都属于链接错误,将在这一步报错。

    过程如下图:

    链接过程
    编译器链接过程

    .c到.exe的流程大概讲述完毕。实际上预处理、编译、汇编和链接都十分复杂,而我们在编写程序时,一般主要关注预处理过程,下文中就预处理进行详细讲解,其余过程都属于编译器的工作,这里不再做介绍。

    2、预处理

    预处理环节是编译器最先进行的一步,编写程序时我们时常调用一些预处理指令。这里主要介绍预处理的二个主要功能:

    1:宏定义

    宏定义只需记住一个词:替换。  (完全替换,连一个标点符号都不放过)

    2:头文件中的应用(条件编译)

    条件编译的主要作用是:增加程序的兼容性

     1:宏定义

    重要的事情再说一遍:宏定义的作用方式就是替换,完全的替换。

    (1)一些预定义的符号
     

    一些预定义符号及功能
    __FILE__ 进行编译的源文件(显示文件的属性信息)
    __LINE__ 文件当前的行号(显示__LINE__所在的行号)
    __DATE__ 文件被编译的日期(显示时间(年月日))
    __TIME__ 文件被编译的时间(显示时间(时分秒))

    实操:

    #include < stdio.h >
    int main()
    {
    	printf("%s\n",__FILE__);
    	printf("%d\n",__LINE__);
    	printf("%s\n", __DATE__);
    	printf("%d\n", __TIME__);
    	return 0;
    }

    结果为:

    运行结果

    这里说明一下这些预定义符号的作用:程序日志(在程序关键地方将这些关键信息进行输出(需要学习C语言文件操作的知识),达到调试的目的)。这个功能将在C语言-文件操作的博客中进行实现。

    (2)宏定义

    宏定义的格式为:#define A B      :作用是,程序中B往往书写较为复杂(名字过长等),这里定义一个A,在程序中直接书写A,就可以达到书写B的效果。

    (1):替换

    在预处理环节,程序中所有出现A的地方,全部被替换为B。

    知识点1:程序中使用宏定义时,千万不要吝啬括号。

    #define ADD(a,b) a+b
    #define ADD1(a,b) ((a)+(b))
    int main()
    {
    	int a = 5;
    	int b = 3;
    	printf("%d\n",10*ADD(a,b));  //运行结果为53
    	printf("%d\n", 10 * ADD1(a, b));//运行结果为80
    	return 0;
    }

    printf("%d\n",10*ADD(a,b));   在经过预处理环节后,程序变为:printf("%d\n",10* a + b);      

    因为宏定义是完全替换,所以,宏定义时千万不要吝啬括号,因为括号的优先级是最高的。

    知识点2:宏定义最后不要加分号

    原因与知识点1一样,宏定义是完全替换。

    如果#define ADD(a,b) ((a) + (b)); 

    那么预处理后,printf("%d\n",10*ADD(a,b));  变为:printf("%d\n",10*((a) + (b)););       这里会出现语法错误。

    (2):预处理环节不进行表达式的计算

    这里插播一条知识点:我们的源文件最终会被编译器编程一个可执行文件(.exe文件)。

    在没有运行.exe文件之前:全局变量、静态常量以及常量字符串在编译环节就已经在内存的静态区分配好了空间。

    这里存在一个问题:如果我们只编译,但不运行,程序没有运行,怎么会在内存中分配空间呢?

    原因:比如我们的Visual Studio这种IDE软件,我们编写好源文件,点击运行,此时IDE的预处理环节就会程序编译环节向内存的静态区申请空间。 如果,我们只是生成.exe文件而不运行,此时全局变量、静态常量以及常量字符串会被存储在.exe特定的节中,当.exe被点击运行后,全局变量、静态常量以及常量字符串会被直接加载到内存的静态区,而不需要额外的代码来向内存开辟空间。

    运行.exe文件之后:程序运行之后,局部变量在定义时,程序会向内存的栈区申请内存,局部变量的生命周期结束后,程序将空间返还给栈区(自动的)。 如果是我们使用专门的函数进行动态内存开辟,此时程序向内存申请的空间是堆区,用完我们需要手动将堆区的空间进行返还

    话有些多,直接上图:

    有了上述的铺垫,我们知道,在预处理环节,程序中的表达式是不计算的,在程序运行中才计算表达式。

    int main()
    {
    	char b = 0;
    	int a = 5;
    	printf("%d\n", sizeof(b = a + 2)); //运行结果为1
    	printf("%d\n", b);          //运行结果为0
    	return 0; 
    }

    sizeof是C语言中的一个关键字,其计算数据的大小(单位为字节)。

    这段程序主要有二点:

    (1)sizeof(b = a + 2))  由于sizeof为关键字,其起作用的阶段为程序的编译阶段,表达式不计算,所以b的值并没有变为7。(注意:b的结果与b的数据类型无关,b的值没变只是因为表达式没有被计算,即sizeof的作用是在程序的编译环节,而不是程序的运行环节)

    (2)无论表达式是否计算(实际上没有计算),sizeof求的都是b所占空间的大小,b为char型,所占大小为1字节。

    (3)#的骚操作

    (1):#可以将参数插入字符串中

    简而言之:一般而言,“  ”之中的是字符串,里面所有的字符不具值的属性,但对于转义字符和#后的字符,要另当别论。

    废话不说,上代码:

    (1)对于宏定义而言:

    宏定义的本质是替换,所以:PRINT("%d",a+6);  等于 printf("the value of " "a+6" " is " "%d" "\n", a+6);   从这里可以看出,宏定义中使用#可以将参数变为字符串(#VALUE == "a+6")

    这里需要注意二点:(1)printf("a""b"); 等于 printf("ab");  (2)#的作用仅仅在宏定义中起作用,不可在函数内调用,否则会出语法错误。并且在宏定义中,#VALUE是不可在""内部。

    (2)对于转义字符而言:

    转义字符不是字符,每个转移字符都有自身的功能。C语言中常用的转义字符如下:

    C语言中常用的转义字符
    转义字符 功能
    \? 用于表示字符 ?
    \' 用于表示字符 '
    \" 用于表示字符 "
    \\ 用于表示字符 \
    \a 警告字符,并使电脑蜂鸣器响一声
    \b 退格符
    \f 进址符
    \n 换行
    \r 回车
    \t 水平制表符
    \v 垂直制表符
    \ddd 用于表示1-3个八进制数
    \xdd

    用于表示2个十六进制数

    (2):##可以将字符串合并为变量名

    需要注意的二点:(1)##的作用也必须在宏定义中,不可在函数内部这样使用。(2)a##b 中 a和b合成后的变量ab必须是已定义的变量名,否则程序会报错。

    (4)宏和函数的区别

    宏:常被我们用于执行简单的运算

    函数:常被我们用来实现复杂法功能,函数的语法较为严谨。

    这里给出二者的详细区别:

    宏与函数的区别
    属性 函数
    代码长度 每次使用时,宏都会插入程序中。 函数只需要定义后,别的函数需要时,直接通过函数地址来调用函数。
    执行速度 较慢(函数的调用和返回需要耗时)
    操作符优先级 宏是直接插入程序之中,需要考虑插入处附近的代码,避免宏插入后产生语法错误 函数是相互独立的,相互直接的调用通过函数地址来进行,不需要考虑那么多操作符优先级的问题
    是否有副作用 宏替换后,会导致一些变量的数值发生改变,这一点要注意 函数直接传递数值,一个函数不会更改另一个函数内部变量的数值(除非通过指针)
    参数类型 宏的本质是替换,只有替换后程序语法正确,不需要在宏中考虑数据类型(这也是宏语法不严谨的原因) 函数传参基本都需要知道参数的数据类型。 (非基本的情况:在C语言—指针文中有介绍)
    调试 不可调试(预处理阶段就替换完了,在程序运行阶段才有调试概念) 可调试
    递归 不可递归 可递归

    宏和函数都是我们写程序时的基本功,要根据二者的区别,根据实际情况来决定使用宏还是函数。

    2:条件编译

    条件编译的目的:增加程序的兼容性

    条件编译的使用场所:在头文件大量使用

    常用的条件编译指令:

    #undef:用于移除一个宏定义

    #if  和#ifdef 和#ifndef     :判断语句(#if 与##ifdef效果相同,如果其后条件为真,则运行之后的代码。 #inndef 如果其后条件为假,则运行之后的代码)

    #elif   :判断分支语句(与else的效果相似)

    #endif  :判断结束语句(#if 与#endif 必须成对出现)

     

    (1)导入头文件

    导入头文件一般有二种方式:

    (1):<stdio.h> 

    这样导入头文件时,IDE直接去库文件所在的位置去查找,如果库文件没有,则报错。

    对于我们直接写的头文件,其位置一般在工程所在目录下,并不在库函数的位置(库函数的位置是安装IDE时就已经确定的)。

    (2):"stdio.h"

    这样导入头文件,IDE先去工程所在目录下去查找,如果没有,再去库文件所在位置去找,如果都没有,则报错。

    对于官方给定的库函数,使用这种方法导入,也可以成功,就是比较耗时。

    (2)头文件的重复导入

    对于一个头文件(特别是库函数),一个工程中会有很多个.c文件需要某个库函数,如果各自都导入,这样无疑会增加程序编译后的代码长度。

    这是因为:每个.c在编译环节都是独立的,都需要各自导入头文件。但在链接环节,连接器将各个目标文件合并为一个.exe,所以,一个头文件在编译环节被导入很多次是无意义的。

    解决办法:当我们在某个.c中需要调用一个头文件时,我们先判断一下这个头文件在工程中其它位置是否已被导入,如果已被导入,则不需要再次导入;如果没有被导入,则次.c中需要导入。

    解决方案一:在我们编写头文件时加上下面的代码

    #ifndef __ADD__    //如果__ADD__ 没有被定义

    #define __ADD__ //定义__ADD__   (这属于无初始化的全局变量,因为我们不需要使用该变量的值,只需要将其定义即可。__ADD__ 在内存中被存储在BBS之中 )

    #endif 

    __ADD__仅仅是一个标识符,可以更改。

    如果我们自己写的一个头文件add.h中加入上述代码后。其余.c要调用add.h时,首先要判断add.h是否已被导入工程中,如果没有则导入,并定于标识符__ADD__,当其它.c文件再导入add.h时就会发现__ADD__已被定义,则不再导入add.h。这样可以避免一个头文件被重复导入。

    解决方案二:#pragma once

    在我们自己写的头文件中加上#pragma once,即可保证头文件不会被重复导入。其作用效果与解决方案一一样。

    (3)条件编译

    假设在程序中,某部分代码使用的条件较为苛刻,但是某些情况下又需要。为了增加程序的兼容性,我们可以将这部分代码放到条件编译之下。需要时可以直接用,不需要时,程序不编译这部分代码,不会使代码冗余。

    火速实操:

    #define AD 1
    int main()
    {
    #if AD
    	printf("%d",1);
    #elif AD==0
    	printf("%d", 0);
    #endif
    	return 0;
    }

    条件编译的语法和if 、else if 的使用方法相似,判断语句都是常量表达式。唯一不同的是判断语句不需要使用括号括起来,并且表达式不需要在花括号内,结束时使用#endif ,而不是使用花括号结束。

    3、结束语

    宏定义最重要的概念的就是替换。记住这一点,我们在使用宏定义时,就会避免很多坑。本文叙述的小知识点较多,希望大家能从这里获取一些新知识。

    展开全文
  • c语言中预处理命令都有哪些

    千次阅读 2013-04-23 21:17:29
    按照ANSI标准定义,预处理程序应该处理以下指令: ...我们可以在C源程序中插入传给编译程序各中指令,这些指令被称为预处理器指令,它们扩充了程序设计的环境。现把常用预处理命令总结如下: 1. 预
  • C语言是一门通用计算机编程语言应用广泛C语言的设计目标是提供一种能以简易的方式编译处理低级存储器产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言接下来看看C语言毕业论文题目有哪些 1针对C语言的...
  • 你必须知道495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    2.17 C语言和Pascalwith等价语句吗? 2.18 既然数组名可以用作数组基地址,为什么对结构不能这样? 2.19 程序运行正确,但退出时却“coredump”(核心转储)了,怎么回事? 联合 2.20 结构和联合...
  • Linux C语言学习笔记

    2020-12-18 11:02:11
    一、C语言的优点有哪些? 简单、快速、高性能、兼容性好、功能强大、易于学习 二、C语言最适合做什么? 三、Linux环境下学习C语言 1.开发环境准备 step1:安装Linux虚拟机 step2:安装文本编辑器 2.编写C语言 step1:...
  • C语言编程要点

    2017-09-18 00:10:37
    12.13. 适用于整数和浮点数数学函数分别有哪些? 184 12.14. 什么是多字节字符(multibyte characters)? 185 12.15. 怎样操作由多字节字符组成字符串? 186 第13章 时间和日期 186 13.1. 怎样把日期存储到单个数字...
  •  本书以问答的形式组织内容,讨论了学习或使用C语言的过程中经常遇到的一些问题。书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预处理器等各个方面的主题,并...
  • 《你必须知道495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    《你必须知道的495个C语言问题》以问答的形式组织内容,讨论了学习或使用C语言的过程中经常遇到的一些问题。书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预...
  • C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准...
  • 2.17 C语言和Pascalwith等价语句吗? 29 2.18 既然数组名可以用作数组基地址,为什么对结构不能这样? 29 2.19 程序运行正确,但退出时却“core dump ”(核心转储)了,怎么回事? 29 联合 30 2.20...
  • 2.17 C语言和Pascalwith等价语句吗?  2.18 既然数组名可以用作数组基地址,为什么对结构不能这样?  2.19 程序运行正确,但退出时却“coredump”(核心转储)了,怎么回事?  联合  2.20 结构和...
  •  2.17 C语言和Pascalwith等价语句吗? 2.18 既然数组名可以用作数组基地址,为什么对结构不能这样? 2.19 程序运行正确,但退出时却“coredump”(核心转储)了,怎么回事? 联合 2.20 结构和联合...
  • 文章目录前言一、C语言的优点有哪些?简单、快速、高性能、兼容性好、功能强大、易于学习二、C语言最适合做什么?三、Linux环境下学习C语言1.开发环境准备step1:安装Linux虚拟机step2:安装文本编辑器2.编写C语言...
  • c语言编写单片机技巧

    2009-04-19 12:15:17
    1. C语言和汇编语言在开发单片机时各有哪些优缺点? 答:汇编语言是一种用文字助记符来表示机器指令符号语言,是最接近机器码一种语言。其主要优点是占用资源少、程序执行效率高。但是不同CPU,其汇编语言...
  • 本书以问答的形式组织内容,讨论了学习或使用C语言的过程中经常遇到的一些问题。书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预处理器等各个方面的主题,并分别...
  •  本书以问答的形式组织内容,讨论了学习或使用C语言的过程中经常遇到的一些问题。书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预处理器等各个方面的主题,并...
  • 你必须知道495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    难道在C语言中一个结构不能包含指向自己指针吗? . . . . 3 1.7 怎样建立和理解非常复杂声明?例如定义一个包含N 个指向返 回指向字符指针函数指针数组? . . . . . . . . . . . . . . 3 1.8 函数只定义...
  • 本书以问答的形式组织内容,讨论了学习或使用C语言的过程中经常遇到的一些问题。书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预处理器等各个方面的主题,并分别...

空空如也

空空如也

1 2 3 4
收藏数 80
精华内容 32
关键字:

c语言的编译环境有哪些

c语言 订阅