什么公司做网站的多,泉州有那些网站建设公司,电影网站源码access,wordpress主题模板文件1.预定义符号 
在C语言中有一些内置的预定义符号 
__FILE__ __LINE__ __DATE__ __TIME__ __STDC__//进行编译的源文件 //文件当前的行号 //文件被编译的日期 //文件被编译的时间 //如果编译器遵循ANSI C#xff0c;其值为1#xff0c;否则未定义 编译器在__STDC__报错,说明,v…1.预定义符号 
在C语言中有一些内置的预定义符号 
__FILE__ __LINE__ __DATE__ __TIME__ __STDC__//进行编译的源文件 //文件当前的行号 //文件被编译的日期 //文件被编译的时间 //如果编译器遵循ANSI C其值为1否则未定义 编译器在__STDC__报错,说明,vs编译器是没有遵循ANSI C的 2.#define 2.1定义标识符 语法 #define name stuff 我们通常会在一条语句写完后带上分号;,但是在#define定义的时候不要加分号!!! 你看出问题所在了吗? #define定义的符号是替换的,那么M就会被替换成100;所以加上分号是一件危险的事情. 2.2定义宏 #define 机制包括了一个规定允许把参数替换到文本中这种实现通常称为宏macro或定义宏define macro。 下面是宏的申明方式 #define name( parament-list ) stuff 其中的 parament-list 是一个由逗号隔开的符号表它们可能出现在stuff中 注意 参数列表的左括号必须与name紧邻。 如果两者之间有任何空白存在参数列表就会被解释为stuff的一部分 但是宏有个特点,我们先来看段代码. 我们想要的结果是8*864,结果输出的却是23,这与我们的预期不符,是为什么呢? 因为宏是替换进去的,此时n  35*35,结果自然就是23,所以我们在定义宏的时候需要加括号以保证正确性,不要吝啬括号. 
结论:对数值表达式进行求值的宏定义都应该用这种方式加上括号避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用. 2.3#define 替换规则 
在程序中扩展#define定义符号和宏时需要涉及几个步骤。 
在调用宏时首先对参数进行检查看看是否包含任何由#define定义的符号。如果是它们首先被替换。替换文本随后被插入到程序中原来文本的位置。对于宏参数名被他们的值所替换。最后再次对结果文件进行扫描看看它是否包含任何由#define定义的符号。如果是就重复上述处理过程 
注意 1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏不能出现递归。 2. 当预处理器搜索#define定义的符号的时候字符串常量的内容并不被搜索。 2.4#和## 
下面我们来探讨如何把参数插入到字符串中! 
字符串是有自动拼接的效果的 因此我们可以这样写代码 但是这里只有当字符串作为宏参数的时候才可以把字符串放在字符串中 
还有一个方法是使用 # 把一个宏参数变成对应的字符串. 此时使用#,就会把参数代入到字符串中 
而##可以把位于它两边的符号合成一个符号,它允许宏定义从分离的文本片段创建标识符 2.5带副作用的宏参数 当宏参数在宏的定义中出现超过一次的时候如果参数带有副作用那么你在使用这个宏的时候就可能出现危险导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。 例如 
x1;//不带副作用
x;//带有副作用 
下面我们写一个宏来证明具有副作用的参数所引起的问题。 2.6宏和函数对比 
宏通常被应用于执行简单的运算。比如在两个数中找出较大的一个。 #define MAX(a, b) ((a)(b)?(a):(b)) 那为什么不用函数来完成这个任务 原因有二 
用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比函数在程序的规模和速度方面更胜一筹。更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以用于来比较的类型。宏是类型无关的 
宏的缺点当然和函数相比宏也有劣势的地方 
每次使用宏的时候一份宏定义的代码将插入到程序中。除非宏比较短否则可能大幅度增加程序的长度。宏是没法调试的宏由于类型无关也就不够严谨。宏可能会带来运算符优先级的问题导致程容易出现错 
宏有时候可以做函数做不到的事情。比如宏的参数可以出现类型但是函数做不到。 宏与函数对比图: 
属 性#define定义宏函数代 码 长 度每次使用时宏代码都会被插入到程序中。除了非常 小的宏之外程序的长度会大幅度增长函数代码只出现于一个地方每 次使用这个函数时都调用那个 地方的同一份代码执 行 速 度更快存在函数的调用和返回的额外开 销所以相对慢一些操 作 符 优 先 级宏参数的求值是在所有周围表达式的上下文环境里 除非加上括号否则邻近操作符的优先级可能会产生 不可预料的后果所以建议宏在书写的时候多些括 号。函数参数只在函数调用的时候求 值一次它的结果值传递给函 数。表达式的求值结果更容易预 测。带 有 副 作 用 的 参 数参数可能被替换到宏体中的多个位置所以带有副作 用的参数求值可能会产生不可预料的结果。函数参数只在传参的时候求值一 次结果更容易控制。参 数 类 型宏的参数与类型无关只要对参数的操作是合法的 它就可以使用于任何参数类型。函数的参数是与类型有关的如 果参数的类型不同就需要不同 的函数即使他们执行的任务是 相同的。调 试宏是不方便调试的函数是可以逐语句调试的递 归宏是不能递归的函数是可以递归的 2.7命名约定 
一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。 所以给友友两个建议: 
把宏名全部大写函数名不要全部大写   3.#undef 
在C语言中#undef是一个预处理指令用于取消定义一个已经定义的宏。 
宏定义是一种在编译时用特定的值或代码片段替换标识符的方式。通过#define指令可以定义一个宏而#undef指令可以取消定义宏。 4.命令行定义 
许多C 的编译器提供了一种能力允许在命令行中定义符号。用于启动编译过程。 例如当我们根据同一个源文件要编译出一个程序的不同版本的时候这个特性有点用处。假定某个程序中声明了一个某个长度的数组如果机器内存有限我们需要一个很小的数组但是另外一个机器内存大些我们需要一个数组能够大些。 
Linux环境下演示: 指令: gcc test.c -D ARRAY_SIZE100 -o test 5.条件编译 
条件编译是一种预处理指令它允许根据条件来选择性地编译代码。条件编译指令在编译阶段进行处理可以根据条件的真假来决定是否编译代码。 
例如 :  调试性的代码删除可惜保留又碍事所以我们可以选择性的编译。 
条件编译使用#if、#ifdef、#ifndef、#elif、#else和#endif等预处理指令来实现。下面列举条件编译指令 
#if和#endif用于指定一个条件如果条件为真则编译条件之间的代码。 #if CONDITION// 代码块
#endif#ifdef和#endif用于检查一个标识符是否已经定义如果已定义则编译条件之间的代码。 #ifdef IDENTIFIER// 代码块
#endif#ifndef和#endif与#ifdef相反用于检查一个标识符是否未定义如果未定义则编译条件之间的代码。 #ifndef IDENTIFIER// 代码块
#endif #elif用于指定一个新的条件如果前面的条件为假且当前条件为真则编译条件之间的代码。 #if CONDITION1// 代码块1
#elif CONDITION2// 代码块2
#else// 代码块3
#endif条件可以是任何可以求值为非零或零的表达式通常使用预定义的宏来表示条件。例如#ifdef指令通常用于检查是否定义了某个宏如下所示 
#include stdio.h#define DEBUGint main() {#ifdef DEBUGprintf(Debug mode\n);#elseprintf(Release mode\n);#endifreturn 0;
}如果定义了宏DEBUG则会编译输出Debug mode否则会编译输出Release mode。 
条件编译可以用于在不同的编译环境下编译不同的代码或者根据不同的条件来选择性地包含或排除代码。它在处理平台特定代码、调试代码和配置选项等方面非常有用。 6.文件包含 我们已经知道 #include 指令可以使另外一个文件被编译。就像它实际出现于 #include 指令的地方一样。 这种替换的方式很简单 预处理器先删除这条指令并用包含文件的内容替换。        这样一个源文件被包含10次那就实际被编译10次。 
6.1头文件被包含的方式 
本地文件包含: #include test.h 查找策略 先在源文件所在目录下查找如果该头文件未找到编译器就像查找库函数头文件一样在标准位置查找头文件。如果找不到就提示编译错误。 
Linux环境的标准头文件的路径 /usr/include VS环境的标准头文件的路径 你如果是默安装路径的话:C:\Program Files (x86)\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\include 注意 : 按照自己的安装路径去找每个人的机器各有差异 库文件包含: #include stdio.h 查找头文件直接去标准路径下去查找如果找不到就提示编译错误。 这样是不是可以说对于库文件也可以使用 “” 的形式包含 答案是肯定的可以。 但是这样做查找的效率就低些当然这样也不容易区分是库文件还是本地文件了 
6.2嵌套文件包含 comm.h和comm.c是公共模块。 test1.h和test1.c使用了公共模块。 test2.h和test2.c使用了公共模块。 test.h和test.c使用了test1模块和test2模块。 这样最终程序中就会出现两份comm.h的内容。这样就造成了文件内容的重复. 
通过前面的学习我们应该都知道了,有不明白的友友可以看这篇程序环境 
头文件在预处理的时候会直接在原地展开,如果一个一个头文件按800行代码计算,如果你重复包含多个的话,那么就会造成冗余,降低程序的运行效率. 
那有没有什么办法可以避免呢? 
1.条件编译 
每个头文件的开头写 
#ifndef __TEST_H__   // 如果未定义标识符__TEST_H__
#define __TEST_H__   // 定义标识符__TEST_H__
// 头文件的内容
#endif //__TEST_H__通过这种方式当多个源文件需要包含同一个头文件时只有第一次包含会生效后续的包含会被忽略避免了头文件的重复包含问题。 
2.#pragma once 
#pragma once是一种用于防止头文件多重包含的预处理指令。与传统的条件编译指令相比#pragma once更简洁和直观。 
使用#pragma once可以确保头文件只被包含一次。当编译器遇到#pragma once指令时它会检查当前的头文件是否已经被包含过如果是则直接跳过该头文件的包含否则继续包含该头文件。 
要使用#pragma once只需要在头文件的开头添加一行#pragma once即可 
#pragma once// 头文件的内容本章内容已完:         如果您喜欢这篇文章可以点赞、评论和分享给您的同学这将对我提供巨大的鼓励和支持。另外我会在未来的更新中持续探讨与c/c相关的内容。我会为您带来更多关于编程技术问题的深入解析、应用案例和趣味玩法等。感兴趣的话给博主点个关注获取最新的内容消息!