⑴ C关于宏的计算
宏在预编译的时候处理,包含#的指令,都是在预编译的时候处理
相对于运行阶段,你也可以认为是编译阶段。
它只是简单的字符串替换,不是计算。
它不影响代码的执行速度,但是可能会增加代码的长度,影响最终生成的可执行文件的大小。
补充:
表达式(10/5)的计算,应该在运行的时候吧
无法通过编译选项控制这个的。
⑵ 在C类语言(C/C++/OC)中经常会用到宏,请问宏在编译期、连接期还是运行期起作用具体发生了什么
宏最主要是预处理时候用的,剩下的编译的时候处理的,某些可能会影响到链接。具体发生什么得看具体什么指令了。
⑶ 宏是什么意思啊,起到什么作用啊
宏,就是“文本替换”,是在编译预处理阶段,宏根据一系列预定义的规则替换一定的文本模式。
以一楼朋友举的例子而言,在预处理期,编译器将你的程序代码里所有出现“MAX”的地方,全都替换成“100”,但是,引号里的内容不换,例如:
printf("MAX");
这句里的MAX不会被替换,它执行的效果是在屏幕上打印出“MAX”三个字母而不是“100”。
for(int i=0; i<MAX; i++)
{
……
}
这里面,“i<MAX”会替换成“i<100”
另外,宏还可以用来简化一些复杂的操作,甚至是带有参数,例如,在视频游戏和动画制作过程中,我们使用大量24位的位图,但我们的显卡往往对24位寻址支持不够好,都使用32位寻址模式,那么我们就要给位图里的每一像素,添加8位ALPHA值,凑成32位,为和显卡配合融洽。
我们习惯使用这样的宏:
#define RGB32BIT(a,r,g,b) ((b)+((g)<<8)+((r)<<16)+((a)<<24))
你会觉得这跟函数有些类似,的确如此,但是,它们很大的区别就是:(带参数)的函数拥有类型检查,而(带参数)的宏没有,就像我上面举的例子,你必须确保a,r,g,b都是正整数,否则就会出错,而使用函数则可以在编译阶段检查出类型错误。不过却要有时间和内存上的开销,而宏没有;所以各有利弊吧!
⑷ const、define、static、extern
extern用于变量的声明,告诉编译器:已经存在一个全局变量,但是不在当前的编译单元内,需要连接的时候在其他编译单元中寻找。
修改变量作用域为当前编译单元,变量生命周期不变;
避免重复定义全局变量
2.2. 修饰局部变量 -
修改变量的生命周期为整个工程周期,变量作用域不变
const修饰右边的变量,用来限制变量为只读属性。
在程序的预编译阶段进行替换处理。
区别:
1.define宏是在预处理阶段展开。
const常量是编译运行阶段使用。
2.define不做检查,不会报编译错误,只是替换。const会编译检查,会报编译错误
3.define在展开的时候才分配内存,展开几次分配几次内存。const在定义的时候会分配一次内存到静态区,使用时不重复分配
4.define可以定义一些简单的运算函数
声明一个只读的静态变量
在多个文件中经常使用的同一个全局变量。
使用场景:
1、.h文件中声明
2、.m文件中赋值
3、pch文件中导入头文件即可在整个项目中访问
这里直接访问即可,都不用放到.pch文件中,因为默认权限是internal
public : 最大权限,可以在当前framework和其他framwork中访问;
internal : 默认权限,可以在当前framework中随意访问;
private : 私有权限,只能在当前文件中访问;
一般常量的话,都用extern const 来代替define。
因为一旦定义#define的方式,整个工程将被重新编译,这样带来的时间浪费可想而知
当然了很多情况还是代替不了的,一般定义常量的时候是应该使用这种方式来定义,不过也只是常量宏不被推荐,但是类函数宏用的还是很方便的,
const、#define的优缺点
编译器可以对const进行类型安全检查。而对#define只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
这种情况还可能出现以下错误
Sending 'const NSString *__strong' to parameter of type 'NSString *' discards qualifiers
原因是需要 NSString* 的地方使用了 const NSString*
.h中 extern const NSString* 替换为 extern NSString* const
.m中 const NSString* 替换为 NSString* const
解释:前者相当于指针本身不可修改,后者表示指针指向的内容不可修改,两者的作用都是使字符串只可读不可写。
⑸ C语言编译系统对宏替换的处理是在什么时候进行的
是正式工作开始之前的准备工作,所以宏替换是在对程序编译之前进行的。
宏替换是C/C++的预处理中的一部分,对于宏定义中的形参,在替换列表中,如果不是作为#或##的操作数,那么将对应实参完全展开(相当于对实参进行求值),然后将替换列表中的形参替换掉,如果是#或##的操作数。
(5)宏处理是在整个编译的哪个阶段扩展阅读:
宏的用途在于自动化频繁使用的序列或者是获得一种更强大的抽象能力。
计算机语言如C语言或汇编语言有简单的宏系统,由编译器或汇编器的预处理器实现。C语言的宏预处理器的工作只是简单的文本搜索和替换,使用附加的文本处理语言如M4,C程序员可以获得更精巧的宏。
宏的行为如同是函数对自身程序文本的变形,并且可以应用全部语言来表达这种变形。一个C宏可以定义一段语法的替换,然而一个Lisp的宏却可以控制一节代码的计算。
⑹ C语言文件的编译与执行的四个阶段并分别描述
开发C程序有四个步骤:编辑、编译、连接和运行。
任何一个体系结构处理器上都可以使用C语言程序,只要该体系结构处理器有相应的C语言编译器和库,那么C源代码就可以编译并连接到目标二进制文件上运行。
1、预处理:导入源程序并保存(C文件)。
2、编译:将源程序转换为目标文件(Obj文件)。
3、链接:将目标文件生成为可执行文件(EXE文件)。
4、运行:执行,获取运行结果的EXE文件。
(6)宏处理是在整个编译的哪个阶段扩展阅读:
将C语言代码分为程序的几个阶段:
1、首先,源代码文件测试。以及相关的头文件,比如stdio。H、由预处理器CPP预处理为.I文件。预编译的。文件不包含任何宏定义,因为所有宏都已展开,并且包含的文件已插入。我归档。
2、编译过程是对预处理文件进行词法分析、语法分析、语义分析和优化,生成相应的汇编代码文件。这个过程往往是整个程序的核心部分,也是最复杂的部分之一。
3、汇编程序不直接输出可执行文件,而是输出目标文件。汇编程序可以调用LD来生成可以运行的可执行程序。也就是说,您需要链接大量的文件才能获得“a.out”,即最终的可执行文件。
4、在链接过程中,需要重新调整其他目标文件中定义的函数调用指令,而其他目标文件中定义的变量也存在同样的问题。
⑺ C语言的编译过程
C编译的整个过程很复杂,大致可以分为以下四个阶段:
预处理阶段在该阶段主要完成对源代码的预处理工作,主要包括对宏定义指令,头文件包含指令,预定义指令和特殊字符的处理,如对宏定义的替换以及文件头中所包含的文件中预定义代码的替换等,总之这步主要完成一些替换工作,输出是同源文件含义相同但内容不同的文件。
编译、优化阶段编译就是将第一阶段处理得到的文件通过词法语法分析等转换为汇编语言。优化包括对中间代码的优化,如删除公共表达式,循环优化等;和对目标代码的生成进行的优化,如如何充分利用机器的寄存器存放有关变量的值,以减少内存访问次数。
汇编阶段将汇编语言翻译成机器指令。
链接阶段链接阶段的主要工作是将有关的目标文件连接起来,即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的目标文件成为一个能够被操作系统装入执行的统一整体。
⑻ C语言enum成员与宏定义作用域的区别
与作用域无关,宏是预编译阶段,在代码中做字符替换,而enum是编译阶段。
整个编译过程是先处理宏,再处理enum类型。
这样写有一个考虑,比如:
#ifdef PTHREAD_PROCESS_PRIVATE
int i=PTHREAD_PROCESS_PRIVATE;
#else
int i=100;
#endif
看出来好处了吗?在不同的开发环境下,只要记得一个名字就可以给变量赋enum成员值,不需要记住二个。
比如下面要记2个词汇aaa和bbb,多不方便,看代码的人又不便理解:
enum{
aaa
#define bbb
}
#ifdef bbb
int i=aaa;
#else
#endif
总结一下:
宏控制不同环境下代码编译,但要用到enum,又要方便使用不用记太多东西,这就是为什么这个代码要这样写,是很高明的做法。
⑼ C语言预处理编译链接各个阶段错误,分阶段的说一下
预处理阶段主要是处理宏指令,像什么#include指令、#define指令还有条件编译指令等。
编译阶段主要是检查C语言程序的语法错误,即编写的代码是否符合C语言规则,编译是以.c源文件为单位编译成.obj文件(或者是.o文件)。
链接阶段,就是把相关的.obj文件、所需的库文件等组合成一个可执行的文件。如果缺少相关所需文件,就会链接报错。
指针异常,数组下标越界这些错误属于语义错误,这个只能在执行的时候才能发现问题,这些也叫运行时错误。
⑽ C语言取消宏定义
宏定义属于预编译阶段的处理过程。预编译是整个编译过程的第一步。编译器将检查代码中的所有预编译语句,遇到#include则将被包含的文件整个复制粘贴到#include位置替换#include语句,遇到#define语句则定义该宏并将文本中所有出现该宏的代码予以替换,遇到#ifdef、#ifndef、#endif语句则进行判断和执行相应操作。这个时候程序的源代码还是文本形式,编译器还没有开始语法分析,连函数的概念都不存在,又怎么判断函数的代码谁先执行谁后执行呢?