首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

长文详解:C语言预处理命令

定义用名来表示一个字符串,在展开又以该字符串取代名。这只是一种简单文本替换,预处理程序对它不作任何检查。如有错误,只能在编译已被展开后源程序时发现。...因为const常量有数据类型,而常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行简单字符文本替换,没有类型安全检查,并且在字符替换可能会产生意料不到错误。...函数只有一个返回值,利用则可以设法得到多个值。 展开使源程序变长,函数调用不会。 展开不占用运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)。...1,因此在条件编译时常量表达式CAPITAL_LETTER真(非零),故运行后使小写字母变成大写(C LANGUAGE)。...用inline函数代替(类似功能)函数。好处如下: 1) 函数在预编译处理,编译出错信息不易理解; 2) 函数本身无法单步跟踪调试,因此也不要在内调用函数

2.6K10

C语言中定义

在一个定义中,编译器可以检测到绝大多数由多余符号所导致错误。但不幸是,编译器会将每一处使用这个地方标错误,而不会直接找到错误根源——定义本身,因为定义已经被预处理器删除了。...(j):(k)))); 2) 、参数没有类型检查。当一个函数被调用时,编译器会检查每一个参数来确认它们是否是正确类型。如果不是,或者将参数转换成正确类型,或者由编译产生一个出错信息。...会在预处理过程中被删除,所以不存在类似的“指向指针”。因此,不能用于处理这些情况。 4) 、可能会不止一次地计算它参数。函数对它参数只会计算一次,而可能会计算两次甚至更多次。...#endif 在编译如果定义了DEBUG则将LOG_MSG当做printf使用,而不需要调试,正式发布则将LOG_MSG()定义空, 由于是在预编译阶段进行处理,所以上面的相当于从代码中删除了...__DATE__ 指令含有形式月/日/年串,表示源文件被翻译到代码日期。 __TIME__ 指令包含程序编译时间。

5.9K10
您找到你想要的搜索结果了吗?
是的
没有找到

【Rust日报】 2019-10-15 使Tokio调度程序快10倍

详细信息前往GitHub查看 Watt:由wasm支持proc(概念验证),编译时间几乎编译速度更快。 ...提前将编译为Wasm,可以节省该所有下游用户时间,他们不必自己编译逻辑或其依赖项。 隔离性。 Watt是100%安全代码,具有零依赖性。...由于Rust编译器或标准库中存在模块错误,因此除了随机播放令牌外不可能做任何其他事情。 确定性。 从系统构建角度来看,由Wasm支持具有以下优点:可以将其视为从输入到输出纯粹确定性函数。...隐式依赖(例如通过文件系统)是不存在,构建系统对隐式依赖不可见或不考虑隐式依赖。 详细信息前往GitHub查看 使Tokio调度程序快10倍方法 调度程序作用是调度工作。...一个应用程序被分解多个工作单元,我们将它们称为任务。当任务可以进展,它是可运行;而在外部资源上被阻塞,该任务将不可可运行(或空闲)。任务是独立,因为任何数量可运行任务都可以同时执行。

64630

C++之内联函数

大家好,又见面了,我是全栈君   C++继承C一个重要特性是效率,在C中保护效率一个方法是使用(macro),实现是使用预处理器而不是编译器,预处理器直接用宏代码替换调用,所以就没有了参数压栈...C++中使用预处理器存在两个问题,一是不安全性,二是C++特有的,预处理器不容许存取私有数据,这意味着预处理器在用作成员函数变得非常无用。   ...内联函数编译器   内联函数使用inline关键字定义,为了使之有效,必须使函数体和声明结合在一起,否则,编译器将它作为普通函数对待   一般应该把内联定义在头文件中,当编译器看到这个定义,它把函数类型...(函数名+返回值)和函数体放到符号表里,当使用函数编译器检查以确保调用和返回是否正确,然后将函数调用替换为函数体,因而消除了开销,内联代码的确占用空间,但假如函数较小,这实际比为了一个普通函数调用而产生代码...,编译器也不能执行内联,因为这时编译器必须函数代码分配内存从而为我们产生一个函数地址。

32310

C++中inline和#define区别总结

,由于 #define 是文本替换而非类型安全操作, 因此可能导致意料之外 错误发生.综上所述:使用 inline: 在想要让编译器内联函数地方使用该关键字,对于中小型、简单且频繁调用函数可以提高程序效率...使用 #define: 在需要定义常量或使用。...但是要注意在使用前进行检查和验证, 避免引入不必要错误.总结来看:处理阶段: 定义define在预处理阶段就换成了字符串替换,而inline在编译阶段进行。...类型安全检查: 定义define是简单字符串替换,不存在类型安全检查,而inline函数还是一个函数编译器会进行类型安全检查,因此inline更加安全。...替换方式: 定义define只是单纯字符串替换,而inline是代码嵌入,也就是说编译器在函数调用地方直接将inline函数代码写进去,这样就不会产生函数调用跳转(无栈帧消耗) ,因此适用于短小函数

14410

Debug和Release之本质区别

,减少链接时间  Release 版本   参数  含义  /MD /ML 或 /MT 使用发布版本运行时刻函数库  /O1 或 /O2 优化开关,使程序最小或最快  /D "NDEBUG" 关闭条件编译调试代码开关...若函数声明与实现不同(参数、返回值、调用方式),就会产生错误????...防止这种错误方法之一是重定义 ON_MESSAGE ,把下列代码加到 stdafx.h 中(在#include "afxwin.h"之后),函数原形错误编译会报错。..._DEBUG 与 NDEBUG :当定义了 _DEBUG ,assert() 函数会被编译,而 NDEBUG 不被编译。除此之外,VC++中还有一系列断言。...要特别注意是,很多人认为编译器会用 0 来初始化变量,这是错误(而且这样很不利于查找错误)。 2.  通过函数指针调用函数,会通过检查栈指针验证函数调用匹配性。(防止原形不匹配) 3.

3.5K90

C语言入门系列之9.预处理

如有错误,只能在编译已被展开后源程序时发现。 (2)定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换。...这与函数情况是不同: 在函数中,形参和实参是两个不同量,各有自己作用域,调用时要把实参值赋予形参,进行值传递; 而在带参中,只是符号代换,不存在值传递问题。...,因为在使用方式,只是简单字符串替换,每次字符串替换都会执行两次i++,所以第一次1×2,第2次3×4,第3次5×6,导致结果不同。...用户编程可根据需要包含文件所在目录来选择某一种命令形式。 四、条件编译 预处理程序提供了条件编译功能,可以按不同条件去编译不同程序部分,因而产生不同目标代码文件。...为了避免代换发生错误定义中字符串应加括号,字符串中出现形式参数两边也应加括号。

61910

gcc命令大全

相关参数有: -E 预编译后停下来,生成后缀 .i 编译文件。 -c 编译后停下来,生成后缀 .o 目标文件。 -S 汇编后停下来,生成后缀 .s 汇编源文件。...其中最有价值的当数 -Wall 了,使用它能够使 gcc 产生尽可能多警告信息。 gcc 给出警告信息虽然从严格意义上说不能算作错误,但却和可能成为错误来源。...一个优秀程序员应该尽量避免产生警告信息,使自己代码始终保持简洁、优美和健壮特性。 (3)-Werror 选项 在处理警告方面,另一个常用编译选项是 -Werror。...它要求 gcc 将所有的警告当成错误进行处理,这在使用自动编译工具(如 Make 等)非常有用。...两者差别仅在程序执行时所需代码是在运行时动态加载,还是在编译静态加载。 默认情况下,gcc 在链接优先使用动态链接库,只有当动态链接库不存在才考虑使用静态链接库。

1.2K20

Swift 周报 第四十三期

根据提供实现替换函数主体。例如,将主体移入在其他地方执行闭包中,或将主体视为“降低”可执行代码特定领域语言。...讨论序言中提出一个具体问题提到,所提议可能无法有效地处理从函数体抛出错误。有人建议使用一种新延迟块来捕获抛出错误,从而允许访问块内这些错误以进行处理。...该对话强调了与处理重复枚举案例名称相关编译错误,该错误使枚举实例唯一性变得复杂。...不可破坏类型概念旨在增强本地数据流分析并提供编译保证。它类似于函数想法,从技术上讲,函数承诺返回一些东西,但实际上却没有,而编译器静态地证明了理论上不可能。...讨论对比了使用和不使用此功能 API 使用难度,强调了需要显式清理面临潜在挑战。对 API 文档、运行时检查和潜在风险仔细研究与用于防止错误使用编译诊断进行了比较。

18410

Swift 周报 第四十三期

根据提供实现替换函数主体。例如,将主体移入在其他地方执行闭包中,或将主体视为“降低”可执行代码特定领域语言。...讨论序言中提出一个具体问题提到,所提议可能无法有效地处理从函数体抛出错误。有人建议使用一种新延迟块来捕获抛出错误,从而允许访问块内这些错误以进行处理。...该对话强调了与处理重复枚举案例名称相关编译错误,该错误使枚举实例唯一性变得复杂。...不可破坏类型概念旨在增强本地数据流分析并提供编译保证。它类似于函数想法,从技术上讲,函数承诺返回一些东西,但实际上却没有,而编译器静态地证明了理论上不可能。...讨论对比了使用和不使用此功能 API 使用难度,强调了需要显式清理面临潜在挑战。对 API 文档、运行时检查和潜在风险仔细研究与用于防止错误使用编译诊断进行了比较。

18410

C++ 入门基础

注意: 命名空间支持嵌套使用 如果出现同名命名空间,编译器会将其合并,可能会引起冲突 命名空间是在编译查找启用 ---- 缺省参数 祖师爷在 C++ 中设计了缺省参数这个概念,使得函数在没有参数传递也可以按其他方式运行...//val是函数 func 中局部变量,当函数结束后,变量就被销毁了 //此时可能得到正确结果(编译器未清理),也可能得到错误结果(编译器已清理) //因此说结果是未定义 //可以看到下图中相同语句出现两种结果...inline 替换函数 总之,很危险,需要少用 所谓内联函数就是在函数实现前加上 inline 修饰,此时函数会被编译器标记为内联函数 //此时 Add 函数就是一个内联函数 inline int...内联函数弥补了函数不足,同时吸收了函数速度快优点 内联函数可以全面替代,当然使用时也需要注意 频繁使用内联函数编译出来可执行程序会更大,因为代码会变多,但运行速度更快 调用内联函数...,是否展开取决于编译器,如果内联函数展开后会影响性能,那么编译器有权不展开内联函数 内联函数适用于代码行数较少,且被频繁调用函数 内联函数不建议声明和定义分开,因为内联函数不进入符号表,因此可能产生链接错误

15210

计算机预处理详解

预定义符号 _FILE_ //进行编译源文件 _LINE_ //文件当前行号 _DATE_ //文件被编译日期 _TIME_ //文件被编译时间 _SDTC_ //如果编译器遵循...2、体替换名是在编译之前就完成函数参数调用是在函数执行时将实参传给形参。...3、参数替换是不经过计算,有可能会带有副作用,所以我们在写时候一般在能加括号地方都不要吝啬括号,但有时候这也不能解决副作用问题。函数在传参是值,不会产生副作用。...4、因为函数是在执行期间调用,所以可以进行调试;编译前完成,所以不可以进行调试。 5、函数支持递归,不支持。...6、函数在调用时会产生时间和空间上开销;在调用时则没有,因为进行只是简单字符串替换。 7、如果使用比较多,体在展开时会产生大量代码,大大降低运行时间。

4900

C语言——R预处理详解

⼀个定义: #define DOUBLE(x) (x) + (x) 定义中我们使⽤了括号,想避免之前问题,但是这个可能会出现新错误。...#define DOUBLE( x) ( ( x ) + ( x ) ) 提示: 所以⽤于对数值表达式进⾏求值定义都应该⽤这种⽅式加上括号,避免在使由于参数中操作符或邻近操作符之间不可预料相互作...所以函数只能在类型合适表达式上使⽤。反之这个怎可以适⽤于整形、⻓整型、浮点型等可以⽤于 > 来⽐较类型。是类型⽆关。 和函数相比劣势: 1....八、命名约定 ⼀般来讲函数使⽤语法很相似。所以语⾔本⾝没法帮我们区分⼆者。...如果找不到就提⽰编译错误

8610

举例分析可变参数函数实现过程

3.被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少参数,甚至完全不同参数都不会产生编译阶段错误。...(简化将就是调用参数类型和数量不会产生编译阶段错误) 以求和函数举例 int sum = sum(3,4,5,6); 三个定义 (1)va_start #define va_start...(2)va_arg #define va_arg(ap,t) (*(t*))(ap += _INTSIZEOF(t) - _INTSIZEOF(t)) va_arg作用: 参数类型: apva_list...(3)va_end #define va_end(ap) (ap = (va_list)0) ap = (char*)0 = NULL; va_end作用: 参数类型: apva_list类型指针...功能: 使指针指向空,不在使用该指针。防止ap成为野指针,进行错误引用。实际上通常va_start与va_end是配对使用。 了解并掌握以上三个使用方法以及函数栈调用规则后。

52120

【C】程序环境和预处理

如图,我们只对函数进行了调用,而函数未定义,就会导致error LNK2019这样错误,此过程中无法解析出有意义符号Add,致使链接发生了错误。...除了非常小之外,程序长度会大幅度增长 函数代码只出现于一个地方;每次使用这个函数,都调用那个地方同一份代码 执行速度 更快 存在函数调用和返回额外开销,所以相对慢一些 操作符优先级 参数求值是在所有周围表达式上下文环境里...函数参数只在函数调用时候求值一次,它结果值传递给函数。表达式求值结果更容易预测。 带有副作用参数 参数可能被替换到体中多个位置,所以带有副作用参数求值可能会产生不可预料结果。...__DEBUG__注释掉,#ifdef后面的定义不存在,就执行#endif后面的内容: 常见条件编译指令: 1....如果找不到就提示编译错误

13930

讲解cl: 命令行 error D8021 :无效数值参数“Wno-cpp” 和 cl: 命令行 error D8021 :无效数值参数“Wno-unu

C++编程,我们可能会遇到名为"cl"命令行编译器和错误消息"D8021: 无效数值参数"。...当我们在使用该参数编译器将不再产生与这些警告相关错误消息或警告信息。 预处理器是C++编译过程中一个重要阶段,它对源代码进行转换和处理。...这种情况下,编译器可能会产生警告信息提示我们可能存在潜在问题。 通过使用/Wno-cpp参数,我们可以在编译禁用此类警告信息。...然而,在某些情况下,可能出现在编写代码早期定义了一些函数,但由于后续需求变化或者其他原因,这些函数并未被调用。在编译大型项目,这可能会导致大量未使用函数警告强噪音,干扰了真正需要关注问题。...通过使用/Wno-unused-function参数,我们可以告诉编译器不再生成与未使用函数相关警告信息。这有助于减少警告消息干扰,使我们更容易聚焦于真正需要解决问题。

59510

C语言被忽视一些小东西!C语言基础教程之错误处理

让我们来模拟一种错误情况,尝试打开一个不存在文件。您可以使用多种方式来输出错误消息,在这里我们使用函数来演示用法。另外有一点需要注意,您应该使用stderr文件流来输出所有的错误。...ordirectory 在进行除法运算,如果不检查除数是否零,则会导致一个运行时错误。...为了避免这种情况发生,下面的代码在进行除法运算前会先检查除数是否零: 当上面的代码被编译和执行时,它会产生下列结果:除数 0 退出运行......通常情况下,程序成功执行完一个操作正常退出时候会带有值 EXIT_SUCCESS。在这里,EXIT_SUCCESS 是,它被定义 0。...所以,上面的程序可以写成: 当上面的代码被编译和执行时,它会产生下列结果: quotient 变量 : 4

61900

C语言之预处理命令与用typedef命名已有类型

定义不是C语句,不必在行未加分号; #define命令出现在程序中函数外面,有限范围定义命令之后到本源文件结束。 可以用#undef命令终止定义作用域。...定义与定义变量不同,只作字符替换,不分配空间;   带参数定义(不只是进行简单字符串替换,还要进行参数替换) 带参数定义与函数不同,主要有以下几点: 函数调用时,先求出实参表达式值,然后带入形参...而只是进行简单字符替换。 函数调用是在程序运行时处理形参分配临时内存单元。而展开则是编译前进行,在展开不分配内存单元,不进行值传递处理,也没有“返回值”概念。...对函数实参和形参都要定义类型,二者要求一致。而不存在类型问题,名无类型。定义,字符串可以是任何类型数据。 调用函数只可得到一个返回值,而用定义可以设法得到几个结果。...头文件除了可以包含函数原型和定义外,也可以包括结构体类型定义和全局变量定义等。   条件编译 程序中某一部分需要满足一定条件才进行编译,也就是对这一部分内容指定编译条件,这就是条件编译

1.5K90
领券