1、位操作2、宏定义3.ifdef条件编译4.extern变量申明5.结构体

合集下载

c语言的预处理指令分3种  1宏定义  2条件编译  3文件包含

c语言的预处理指令分3种  1宏定义  2条件编译  3文件包含

c语⾔的预处理指令分3种 1宏定义 2条件编译 3⽂件包含宏简介1.C语⾔在对源程序进⾏编译之前,会先对⼀些特殊的预处理指令作解释(⽐如之前使⽤的#include⽂件包含指令),产⽣⼀个新的源程序(这个过程称为编译预处理),之后再进⾏通常的编译所有的预处理指令都是以#开头,并且结尾不⽤分号2.预处理指令分3种 1> 宏定义 2> 条件编译 3> ⽂件包含3.预处理指令在代码翻译成0和1之前执⾏4.预处理的位置是随便写的5.预处理指令的作⽤域:从编写指令的那⼀⾏开始,⼀直到⽂件结尾,可以⽤#undef取消宏定义的作⽤6.宏名⼀般⽤⼤写或者以k开头,变量名⼀般⽤⼩写 宏定义可以分为2种:不带参数的宏定义和带参数的宏定义。

⼀、不带参数的宏定义1.⼀般形式#define 宏名字符串⽐如#define ABC 10右边的字符串也可以省略,⽐如#define ABC2.作⽤它的作⽤是在编译预处理时,将源程序中所有"宏名"替换成右边的"字符串",常⽤来定义常量.3.使⽤习惯与注意1> 宏名⼀般⽤⼤写字母,以便与变量名区别开来,但⽤⼩写也没有语法错误2> 对程序中⽤双引号扩起来的字符串内的字符,不进⾏宏的替换操作。

3> 在编译预处理⽤字符串替换宏名时,不作语法检查,只是简单的字符串替换。

只有在编译的时候才对已经展开宏名的源程序进⾏语法检查4> 宏名的有效范围是从定义位置到⽂件结束。

如果需要终⽌宏定义的作⽤域,可以⽤#undef命令5> 定义⼀个宏时可以引⽤已经定义的宏名#define R 3.0#define PI 3.14#define L 2*PI*R#define S PI*R*R举例1 #include <stdio.h>2#define COUNT 434int main()5 {6char *name = "COUNT";78 printf("%s\n", name);910int ages[COUNT] = {1, 2, 67, 89};1112#define kCount 41314for ( int i = 0; i<COUNT; i++) {15 printf("%d\n", ages[i]);16 }1718// 从这⾏开始,COUNT这个宏就失效19#undef COUNT2021//int a = COUNT 写这个报错2223return0;24 }⼆、带参数的宏定义1.⼀般形式#define 宏名(参数列表) 字符串2.作⽤在编译预处理时,将源程序中所有宏名替换成字符串,并且将字符串中的参数⽤宏名右边参数列表中的参数替换3.使⽤注意1> 宏名和参数列表之间不能有空格,否则空格后⾯的所有字符串都作为替换的字符串2> 带参数的宏在展开时,只作简单的字符和参数的替换,不进⾏任何计算操作。

c 函数内部宏定义

c 函数内部宏定义

c 函数内部宏定义C函数内部宏定义一、参数检查宏定义在函数内部,我们经常需要对参数进行检查,以确保参数的合法性。

为了简化参数检查的代码,我们可以使用宏定义来实现。

下面是一个示例:```#define CHECK_PARAM(param) \if (!(param)) { \printf("参数错误:%s\n", #param); \return; \}```在上面的示例中,我们定义了一个宏CHECK_PARAM,该宏接受一个参数param,并在参数为假时输出错误信息并返回。

通过使用这个宏,我们可以简化参数检查的代码,提高代码的可读性和可维护性。

二、条件编译宏定义在函数内部,有时我们需要根据不同的条件编译不同的代码。

为了简化条件编译的代码,我们可以使用宏定义来实现。

下面是一个示例:```#define DEBUG_MODE#ifdef DEBUG_MODE#define DEBUG_LOG(...) printf(__VA_ARGS__)#else#define DEBUG_LOG(...)#endif```在上面的示例中,我们定义了一个宏DEBUG_MODE,该宏用于开启或关闭调试模式。

当DEBUG_MODE被定义时,宏DEBUG_LOG会输出调试信息;当DEBUG_MODE未被定义时,宏DEBUG_LOG为空宏。

通过使用这个宏,我们可以方便地在调试模式和发布模式之间切换,提高代码的可维护性。

三、局部变量宏定义在函数内部,有时我们需要定义一些局部变量来辅助实现某些功能。

为了简化局部变量的定义,我们可以使用宏定义来实现。

下面是一个示例:```#define LOCAL_VAR(type, name, value) \type name = value;```在上面的示例中,我们定义了一个宏LOCAL_VAR,该宏接受三个参数:变量的类型type、变量的名称name和变量的初始值value。

c语言define的用法举例

c语言define的用法举例

c语言define的用法举例一、c语言中define的基本用法C语言中的宏定义(define)是一种预处理指令,用于在程序编译之前将某个标识符替换为指定的文本。

它可以提高代码的可读性和灵活性,并简化代码编写过程。

在本文中,我们将介绍define的基本用法,并通过多个示例来说明其具体应用。

1. 定义常量#define可以用于定义常量,即将一个标识符替换为一个固定值。

下面是一个示例:```#define PI 3.14159```在这个示例中,我们将标识符PI定义为3.14159,之后在程序中使用PI时都会被替换为3.14159。

这样做的好处是,在整个程序中使用同样的固定值时只需更改一次即可。

2. 定义简单函数#define还可以定义简单函数,在预处理阶段将函数名替换为相应的代码块。

例如:```#define SQUARE(x) ((x)*(x))```在这个示例中,我们定义了一个计算平方的宏函数SQUARE(x),其中参数x 被使用两次。

当我们在程序中调用SQUARE(x)时,预处理器会将其转换为((x)*(x))并插入到对应位置。

3. 定义带有参数和逻辑操作符的宏函数除了简单函数外,#define还可以定义带有参数和逻辑操作符的宏函数。

下面是一个示例:```#define MAX(x, y) ((x) > (y) ? (x) : (y))```在这个示例中,我们定义了一个找到两个数较大值的宏函数MAX(x, y),其中使用了三目运算符(?:)进行条件判断。

当我们在程序中调用MAX(x, y)时,预处理器会将其转换为((x) > (y) ? (x) : (y))并插入到对应位置。

二、c语言中define的高级应用除了基本使用方式之外,C语言中的define还有一些高级应用,可以提供更强大的功能。

1. 使用#if和#ifdef进行条件编译在编写复杂程序时,常常需要根据不同的条件来编译特定的代码块。

c语言 宏命名规则

c语言 宏命名规则

c语言宏命名规则摘要:1.宏命名规则的概述2.宏命名规则的组成3.宏命名规则的注意事项正文:C 语言是一种广泛使用的编程语言,它具有丰富的语法结构和功能。

在C 语言编程中,宏定义是一种重要的技术,可以帮助程序员简化代码和提高代码的可读性。

本文将介绍C 语言宏命名规则的相关知识。

一、宏命名规则的概述在C 语言中,宏定义是一种用于表示某个符号或表达式的方法。

通过宏定义,程序员可以使用一个简短的名称来表示一段复杂的代码,从而简化代码结构。

宏命名规则是指在定义宏时,需要遵循的命名规范。

二、宏命名规则的组成1.宏名宏名是宏定义中的名称,用于表示宏所代表的含义。

在C 语言中,宏名通常使用大写字母组成,这样可以与其他变量和函数区分开来。

例如,我们可以定义一个宏名MAX,表示两个数中的最大值。

2.宏体宏体是宏定义中的实际内容,它包含了宏所代表的代码或表达式。

在定义宏时,需要保证宏体的正确性和合法性。

例如,我们可以定义一个宏体,用于计算两个数中的最大值:```#define MAX(a, b) ((a) > (b)? (a) : (b))```三、宏命名规则的注意事项1.避免与关键字冲突在定义宏名时,应避免与C 语言的关键字冲突。

关键字是C 语言中具有特定意义的单词,不能作为变量名或宏名使用。

例如,我们不能定义一个名为if 的宏,因为它与C 语言中的if 关键字冲突。

2.避免使用非法字符在定义宏名时,应避免使用非法字符。

非法字符是指C 语言中不允许出现在标识符(如变量名、函数名、宏名等)中的字符。

例如,我们不能定义一个包含空格的宏名,因为空格是非法字符。

3.宏名应具有描述性在定义宏名时,应尽量使其具有描述性,以便于其他程序员理解宏的含义。

例如,我们可以定义一个名为MAX_TEMP 的宏,表示某个温度的最大值。

总之,了解和掌握C 语言宏命名规则对于编程工作非常重要。

C语言中extern关键字详解

C语言中extern关键字详解

extern int div(int x,int y); #endif 文件b.c的内容: #include <stdio.h> int add(int x,int y) { return(x+y); } int sub(int x,int y) { return(x-y); } int mult(int x,int y) { return(x*y); } int div(int x,int y) { if(y!=0) { return(x/y); } printf("mult() fail!the second para can not be zero!\n "); return(-1); } 利用gcc工具编译gcc a.c b.c –o demo,再运行./demo,结果为 x = 10,y = 5 x + y = 15 x-y=5 x * y = 50 x / y = 2。 小结:由上面简单的例子可以看出,在b.h文件中声明好b.c的函数,使 用时,只需要在a.c中包含#include “b.h”头文件即可,这样就可以使用b.c 的接口函数了,在实际工程中,通常也是采用这种方式,.c文件中实现 函数,.h文件中声明函数借口,需要调用.c文件的函数接口时,只需包 含.h头文件即可。
小结:这种用方法简单,实用性不大。 (2) 在多个文件中声明外部变量 作用域:如果整个工程由多个文件组成,在一个文件中想引用 另外一个文件中已经定义的外部变量时,则只需在引用变量的文件 中用extern关键字加以声明即可。可见,其作用域从一个文件扩展 到多个文件了。 例子: 文件a.c的内容: #include <stdio.h> int BASE=2; //变量定义 int exe(int x); //外部函数提前声明 int main(int argc, char *agrv[]) { int a=10; printf("%d^%d = %d\n",BASE,a,exe(a)); return 0; } 文件b.c的内容: #include <stdio.h> extern BASE; //外部变量声明 int exe(int x) { int i; int ret=1; for(i=0;i<x;i++) { ret*=BASE; } return ret; } 利用gcc工具编译gcc a.c b.c –o demo,再运行./demo,结果为 2^10 = 1024。其中,在a.c文件中定义BASE=2,在b.c中引用BASE 时,需要用extern关键字声明其为外部变量,否则编译会找不到该 变量。 小结:对于多个文件的工程,可以采用这种方法来操作。实际 工程中,对于模块化的程序文件,在其文件中可以预先留好外部变

c 语言define详解

c 语言define详解

c 语言define详解在C语言中,`define`是一个预处理指令,用于定义常量或宏。

它告诉编译器在编译之前替换特定的代码或文本。

以下是`define`的一些常见用法:1. 定义常量:使用`define`可以定义常量。

例如:```cdefine PI```在代码中,每当你使用`PI`,它都会被替换为``。

2. 定义宏:`define`也可以定义简单的宏。

例如:```cdefine MAX(a, b) ((a) > (b) ? (a) : (b))```当你在代码中使用`MAX(x, y)`时,它会被替换为`((x) > (y) ? (x) : (y))`。

3. 条件编译:使用`if`、`ifdef`、`ifndef`等预处理指令,你可以根据是否定义了某个宏来决定是否编译某段代码。

例如:```cifdef DEBUG// 当DEBUG被定义时,编译以下代码printf("Debugging information\n");endif```4. 文本替换:除了简单的常量替换,你还可以使用复杂的文本替换。

例如:```cdefine FOO(x) printf("The value of x is: %d\n", x)```这样,每次使用`FOO(y)`时,它都会被替换为`printf("The value of xis: %d\n", y)`。

5. 注意点:预处理指令(如`define`)是在编译之前执行的,所以它们不会进行类型检查或作用域限制。

这意味着如果你在定义宏时犯了一个错误,那么这个错误可能会在整个代码中传播。

使用宏时要小心,因为它们可能会引发一些意想不到的副作用,特别是当宏参数中包含运算符或逗号时。

为了避免这些问题,可以使用括号来确保正确的优先级和运算顺序。

例如:在上面的`MAX`宏中,我们使用了括号来确保正确的运算顺序。

c语言宏定义用法规则

c语言宏定义用法规则

c语言宏定义用法规则C语言宏定义是一种C语言中最常使用的技术,它可以将经常使用的长句子等缩短,可以将复杂的语句也变得更加简单。

使用宏定义,可以提高程序的可读性,使程序更加便于维护和修改,并且可以更加高效地使用程序。

一、宏定义的语法形式C语言的宏定义的语法有以下几种格式:1. #define:#define宏定义用于定义字符串宏或符号宏,本质上它就是把特定的字符串或符号,映射到一个相应的宏名称。

例如:#define PI 3.14159293表示宏定义一个PI,其值为3.141592932. #undef:#undef用于取消宏定义,例如:#undef PI表示取消之前定义流程中的PI宏定义;3. #ifdef:#ifdef可以根据宏定义的存在与否,在程序编译时有选择性的执行一段代码,例如:#ifdef PIprintf("PI is define\n");#endif上述代码表示:如果PI的宏定义存在的话,则编译执行printf("PI is define\n"),否则不执行。

C语言宏定义可以使用参数,这些参数可以是函数、符号、字符串或者表达式,它们都可以在宏定义中扮演角色,使用参数可以提高宏的可扩展性,从而提高程序的复用性,简化程序的结构。

1. 宏定义参数的表示参数的格式使用形式参数名称来表示,一般使用字母a~z表示参数,形式参数可以使用多次,但参数名必须是唯一的。

例如:#define MIN(x, y) ((x) < (y))? (x): (y)这是一个使用参数的宏定义示例,其中参数x,y是表示形式参数的名称,宏定义的意思是返回x和y的较小值。

使用宏定义参数需要在宏定义时明确参数的含义,每个参数都必须有明确的含义,有利于后续的维护和修改。

例如:三、C语言宏定义书写规范1. #define是注释符号,使用时要在一行的开头,以#开头,表示此行的内容是宏定义,且宏定义的关键词必须全大写。

c语言extern的用法

c语言extern的用法

c语言extern的用法在C语言中,extern关键字用于声明一个全局变量或函数,该变量或函数可以在其他文件中定义和使用。

extern关键字有以下几种常见用法:1. 声明全局变量:在一个文件中使用extern关键字声明一个全局变量,然后在其他文件中定义该变量。

这样可以实现多个文件共享同一个全局变量。

Example:file1.c中:extern int globalVariable; // 声明全局变量file2.c中:int globalVariable = 10; // 定义全局变量2. 声明全局函数:在一个文件中使用extern关键字声明一个全局函数,然后在其他文件中定义该函数。

这样可以实现多个文件共享同一个全局函数。

Example:file1.c中:extern void function(); // 声明全局函数file2.c中:void function() // 定义全局函数{// 函数实现}3. 声明外部变量:在一个文件中使用extern关键字声明一个变量,该变量可以是其他文件中定义的全局变量。

这样可以在当前文件中使用其他文件中定义的全局变量。

Example:file1.c中:extern int globalVariable; // 声明外部变量file2.c中:int globalVariable = 10; // 定义全局变量file3.c中:extern int globalVariable; // 声明外部变量void function(){int localVar = globalVariable; // 使用外部变量// 其他操作}4. 声明外部函数:在一个文件中使用extern关键字声明一个函数,该函数可以是其他文件中定义的全局函数。

这样可以在当前文件中调用其他文件中定义的全局函数。

Example:file1.c中:extern void function(); // 声明外部函数file2.c中:void function() // 定义全局函数{// 函数实现}file3.c中:extern void function(); // 声明外部函数void otherFunction(){function(); // 调用外部函数// 其他操作}。

C语言三种预处理功能

C语言三种预处理功能
2、 带参宏一般用法
比如#define MAX(a,b) ((a)>(b)?(a):(b))则遇到 MAX(1+2,value)则会把它替换成: ((1+2)>(value)?(1+2):(value))注意事项和无参宏差不多。 但还是应注意
#define FUN(a) "a"
则,输入 FUN(345)会被替换成什么? 其实,如果这么写,无论宏的实参是什么,都不会影响其被替换成"a"的命运。也就是说, ""内的字符不被当成形参,即使它和一模一样。那么,你会问了,我要是想让这里输入 FUN(345)它就替换成"345"该怎么实现呢?请看下面关于#的用法
带参数
除了一般的字符串替换,还要做参数代换
格式: #define 宏名(参数表) 字符串
例如:
#define S(a,b) a*b area=S(3,2);//第一步被换为 area=a*b; ,第二步被换为 area=3*2;
(1)实参如果是表达式容易出问题
#define S(r) r*r area=S(a+b);//第一步换为 area=r*r;,第二步被换为 area=a+b*a+b;
值传递、返回值)。
冷门重点编辑
#define 用法
1、用无参宏定义一个简单的常量
#define LEN 12
这个是最常见的用法,但也会出错。比如下面几个知识点你会吗?可以看下:
(1)#define NAME "zhangyuncong" 程序中有"NAME"则,它会不会被替换呢? (2)#define 0x abcd 可以吗?也就是说,可不可以用不是标识符的字母替换成别的东 西? (3)#define NAME "zhang 这个可以吗? (4)#define NAME "zhangyuncong" 程序中有上面的宏定义,并且,程序里有句: NAMELIST 这样,会不会被替换成"zhangyuncong"LIST 四个题答案都是十分明确的。 第一个,""内的东西不会被宏替换。这一点应该大家都知道; 第二个,宏定义前面的那个必须是合法的用户标识符; 第三个,宏定义也不是说后面东西随便写,不能把字符串的两个""拆开; 第四个:只替换标识符,不替换别的东西。NAMELIST 整体是个标识符,而没有 NAME 标识符,所以不替换。 也就是说,这种情况下记住:#define 第一位置第二位置 (1) 不替换程序中字符串里的东西; (2) 第一位置只能是合法的标识符(可以是关键字); (3) 第二位置如果有字符串,必须把""配对; (4) 只替换与第一位置完全相同的标识符。 还有就是老生常谈的话:记住这是简单的替换而已,不要在中间计算结果,一定要替换出 表达式之后再算。

c语言中常用的宏定义

c语言中常用的宏定义

c语言中常用的宏定义C语言中常用的宏定义在C语言中,宏定义是一种预处理指令,用于在编译前将代码中的标识符替换为指定的文本。

宏定义可以提高代码的可读性和可维护性,减少代码的重复性,提高开发效率。

下面将介绍一些常用的宏定义。

1. #define#define是C语言中最常用的宏定义指令之一,用于定义一个宏。

它的基本语法为:#define 宏名替换文本宏名可以是任意合法的标识符,替换文本可以是任意合法的C代码。

当程序中出现宏名时,预处理器会将其替换为相应的文本。

2. #ifdef / #ifndef / #endif这三个宏定义指令用于条件编译。

#ifdef用于检查一个宏是否已经定义,#ifndef则用于检查一个宏是否未定义。

如果条件成立,接下来的代码将被编译,否则将被忽略。

#endif用于结束条件编译指令的范围。

3. #if / #elif / #else这些宏定义指令也用于条件编译。

#if用于判断一个常量表达式的值是否为真,如果为真,则接下来的代码将被编译。

#elif用于在多个条件中选择一个进行编译,如果前面的条件不成立,则判断下一个条件。

#else用于指定当前面的条件都不成立时要编译的代码。

4. #undef#undef用于取消一个已定义的宏。

当不再需要某个宏时,可以使用#undef将其取消定义。

5. #include#include是C语言中用于包含头文件的宏定义指令。

头文件中通常包含了一些函数的声明、宏定义和结构体的定义等。

使用#include 可以将头文件的内容插入到当前文件中。

6. #pragma#pragma是一种特殊的宏定义指令,它用于控制编译器的行为。

不同的编译器支持的#pragma指令有所不同,常用的#pragma指令有#pragma once(用于防止头文件的重复包含)、#pragma warning(用于控制编译器的警告信息)等。

7. #line#line用于修改编译器产生的行号和文件名。

c语言中的条件编译

c语言中的条件编译

c语言中的条件编译摘要:一、条件编译的概述1.条件编译的定义2.条件编译的作用二、条件编译的语法1.宏定义的方式2.条件编译的语法结构三、条件编译的应用场景1.代码的调试与优化2.针对不同平台的编译3.国际化与本地化四、条件编译的注意事项1.避免代码重复2.确保编译效率正文:条件编译是C语言中一种非常重要的特性,它允许程序员根据不同的条件包含或排除部分代码。

这种特性使得程序员可以在一个源文件中编写针对不同平台的代码,或者根据不同的编译选项来调整程序的行为。

本文将详细介绍条件编译的概述、语法、应用场景以及注意事项。

一、条件编译的概述条件编译,顾名思义,是根据一定的条件来决定是否编译某一段代码。

在C语言中,条件编译主要通过宏定义和条件语句来实现。

条件编译可以帮助程序员提高代码的复用性、可维护性和可扩展性。

二、条件编译的语法条件编译的语法主要包括宏定义和条件语句两部分。

1.宏定义的方式在C语言中,宏定义是通过预处理器来实现的。

预处理器在编译之前会处理源文件中的宏定义,将宏名替换为宏体。

宏定义的基本语法如下:```c#define 宏名宏体```其中,宏名是一个标识符,用于表示宏,宏体是要替换的代码。

例如:```c#define DEBUG 1```2.条件编译的语法结构条件编译主要通过ifdef、ifndef、else、elif和endif等预处理指令来实现。

这些指令在预处理阶段被处理,用于根据不同的条件包含或排除代码。

条件编译的基本语法如下:```c#ifdef 宏名代码块1#else代码块2#endif```例如,我们可以根据是否定义了DEBUG宏来决定是否包含调试代码:```c#ifdef DEBUG// 调试代码#endif```三、条件编译的应用场景条件编译在实际编程中有广泛的应用,主要包括以下场景:1.代码的调试与优化在开发过程中,程序员通常需要编写调试代码以定位问题。

条件编译可以帮助我们轻松地开启或关闭调试代码,以便在编译时选择是否包含调试功能。

C语言中的预编译宏定义

C语言中的预编译宏定义

C语言中的预编译宏定义C语言中的预编译宏定义导语:C初学者可能对预处理器没什么概念,这是情有可原,下面是C中的预编译宏定义,一起来学习下吧:(一) 预处理命令简介预处理命令由#(hash字符)开头, 它独占一行, #之前只能是空白符. 以#开头的语句就是预处理命令, 不以#开头的语句为C中的代码行. 常用的预处理命令如下:#define 定义一个预处理宏#undef 取消宏的定义#include 包含文件命令#include_next 与#include相似, 但它有着特殊的用途#if 编译预处理中的条件命令, 相当于C语法中的if语句#ifdef 判断某个宏是否被定义, 若已定义, 执行随后的语句#ifndef 与#ifdef相反, 判断某个宏是否未被定义#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif 之后的语句, 相当于C语法中的else-if#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else 之后的语句, 相当于C语法中的else#endif #if, #ifdef, #ifndef这些条件命令的结束标志.defined 与#if, #elif配合使用, 判断某个宏是否被定义#line 标志该语句所在的行号# 将宏参数替代为以参数值为内容的字符窜常量## 将两个相邻的标记(token)连接为一个单独的标记#pragma 说明编译器信息#warning 显示编译警告信息#error 显示编译错误信息(二) 预处理的文法预处理并不分析整个源代码文件, 它只是将源代码分割成一些标记(token), 识别语句中哪些是C语句, 哪些是预处理语句. 预处理器能够识别C标记, 文件名, 空白符, 文件结尾标志.预处理语句格式: #command name(...) token(s)1, command预处理命令的名称, 它之前以#开头, #之后紧随预处理命令, 标准C允许#两边可以有空白符, 但比较老的编译器可能不允许这样. 若某行中只包含#(以及空白符), 那么在标准C中该行被理解为空白. 整个预处理语句之后只能有空白符或者注释, 不能有其它内容.2, name代表宏名称, 它可带参数. 参数可以是可变参数列表(C99).3, 语句中可以利用""来换行.e.g.# define ONE 1 /* ONE == 1 */等价于: #define ONE 1#define err(flag, msg) if(flag)printf(msg)等价于: #define err(flag, msg) if(flag) printf(msg)(三) 预处理命令详述1, #define#define命令定义一个宏:#define MACRO_NAME(args) tokens(opt)之后出现的MACRO_NAME将被替代为所定义的标记(tokens). 宏可带参数, 而后面的标记也是可选的.对象宏不带参数的宏被称为"对象宏(objectlike macro)"#define经常用来定义常量, 此时的宏名称一般为大写的字符串. 这样利于修改这些常量.e.g.#define MAX 100int a[MAX];#ifndef __FILE_H__#define __FILE_H__#include "file.h"#endif#define __FILE_H__ 中的宏就不带任何参数, 也不扩展为任何标记. 这经常用于包含头文件.要调用该宏, 只需在代码中指定宏名称, 该宏将被替代为它被定义的内容.函数宏带参数的宏也被称为"函数宏". 利用宏可以提高代码的运行效率: 子程序的调用需要压栈出栈, 这一过程如果过于频繁会耗费掉大量的CPU运算资源. 所以一些代码量小但运行频繁的代码如果采用带参数宏来实现会提高代码的运行效率.函数宏的参数是固定的情况函数宏的定义采用这样的方式: #define name( args ) tokens其中的args和tokens都是可选的. 它和对象宏定义上的区别在于宏名称之后不带括号.注意, name之后的左括号(必须紧跟name, 之间不能有空格, 否则这就定义了一个对象宏, 它将被替换为以(开始的字符串. 但在调用函数宏时, name与(之间可以有空格.e.g.#define mul(x,y) ((x)*(y))注意, 函数宏之后的参数要用括号括起来, 看看这个例子:e.g.#define mul(x,y) x*y"mul(1, 2+2);" 将被扩展为: 1*2 + 2同样, 整个标记串也应该用括号引用起来:e.g.#define mul(x,y) (x)*(y)sizeof mul(1,2.0) 将被扩展为 sizeof 1 * 2.0调用函数宏时候, 传递给它的参数可以是函数的返回值, 也可以是任何有意义的语句:e.g.mul (f(a,b), g(c,d));e.g.#define (stmt) stmt( a=1; b=2;) 相当于在代码中加入 a=1; b=2 .( a=1, b=2;) 就有问题了: 预处理器会提示出错: 函数宏的参数个数不匹配. 预处理器把","视为参数间的分隔符.((a=1, b=2;)) 可解决上述问题.在定义和调用函数宏时候, 要注意一些问题:1, 我们经常用{}来引用函数宏被定义的内容, 这就要注意调用这个函数宏时的";"问题.example_3.7:#define swap(x,y) { unsigned long _temp=x; x=y; y=_tmp}如果这样调用它: "swap(1,2);" 将被扩展为: { unsigned long _temp=1; 1=2; 2=_tmp};明显后面的;是多余的, 我们应该这样调用: swap(1,2)虽然这样的调用是正确的, 但它和C语法相悖, 可采用下面的方法来处理被{}括起来的内容:#define swap(x,y)do { unsigned long _temp=x; x=y; y=_tmp} while (0)swap(1,2); 将被替换为:do { unsigned long _temp=1; 1=2; 2=_tmp} while (0);在Linux内核源代码中对这种do-while(0)语句有这广泛的应用.2, 有的函数宏是无法用do-while(0)来实现的, 所以在调用时不能带上";", 最好在调用后添加注释说明.eg_3.8:#define incr(v, low, high)for ((v) = (low),; (v) <= (high); (v)++)只能以这样的形式被调用: incr(a, 1, 10) /* increase a form 1 to 10 */函数宏中的参数包括可变参数列表的情况C99标准中新增了可变参数列表的内容. 不光是函数, 函数宏中也可以使用可变参数列表.#define name(args, ...) tokens#define name(...) tokens"..."代表可变参数列表, 如果它不是仅有的'参数, 那么它只能出现在参数列表的最后. 调用这样的函数宏时, 传递给它的参数个数要不少于参数列表中参数的个数(多余的参数被丢弃).通过__VA_ARGS__来替换函数宏中的可变参数列表. 注意__VA_ARGS__只能用于函数宏中参数中包含有"..."的情况.e.g.#ifdef DEBUG#define my_printf(...) fprintf(stderr, __VA_ARGS__)#else#define my_printf(...) printf(__VA_ARGS__)#endiftokens中的__VA_ARGS__被替换为函数宏定义中的"..."可变参数列表.注意在使用#define时候的一些常见错误:#define MAX = 100#define MAX 100;=, ; 的使用要值得注意. 再就是调用函数宏是要注意, 不要多给出";".注意: 函数宏对参数类型是不敏感的, 你不必考虑将何种数据类型传递给宏. 那么, 如何构建对参数类型敏感的宏呢? 参考本章的第九部分, 关于"##"的介绍.关于定义宏的另外一些问题(1) 宏可以被多次定义, 前提是这些定义必须是相同的. 这里的"相同"要求先后定义中空白符出现的位置相同, 但具体的空白符类型或数量可不同, 比如原先的空格可替换为多个其他类型的空白符: 可为tab, 注释...e.g.#define NULL 0#define NULL /* null pointer */ 0上面的重定义是相同的, 但下面的重定义不同:#define fun(x) x+1#define fun(x) x + 1 或: #define fun(y) y+1如果多次定义时, 再次定义的宏内容是不同的, gcc会给出"NAME redefined"警告信息.应该避免重新定义函数宏, 不管是在预处理命令中还是C语句中, 最好对某个对象只有单一的定义. 在gcc中, 若宏出现了重定义, gcc会给出警告.(2) 在gcc中, 可在命令行中指定对象宏的定义:e.g.$ gcc -Wall -DMAX=100 -o tmp tmp.c相当于在tmp.c中添加" #define MAX 100".那么, 如果原先tmp.c中含有MAX宏的定义, 那么再在gcc调用命令中使用-DMAX, 会出现什么情况呢?---若-DMAX=1, 则正确编译.---若-DMAX的值被指定为不为1的值, 那么gcc会给出MAX宏被重定义的警告, MAX的值仍为1.注意: 若在调用gcc的命令行中不显示地给出对象宏的值, 那么gcc 赋予该宏默认值(1), 如: -DVAL == -DVAL=1(3) #define所定义的宏的作用域宏在定义之后才生效, 若宏定义被#undef取消, 则#undef之后该宏无效. 并且字符串中的宏不会被识别e.g.#define ONE 1sum = ONE + TWO /* sum = 1 + TWO */#define TWO 2sum = ONE + TWO /* sum = 1 + 2 */#undef ONEsum = ONE + TWO /* sum = ONE + 2 */char c[] = "TWO" /* c[] = "TWO", NOT "2"! */(4) 宏的替换可以是递归的, 所以可以嵌套定义宏.e.g.# define ONE NUMBER_1# define NUMBER_1 1int a = ONE /* a = 1 */2, #undef#undef用来取消宏定义, 它与#define对立:#undef name如够被取消的宏实际上没有被#define所定义, 针对它的#undef 并不会产生错误.当一个宏定义被取消后, 可以再度定义它.3, #if, #elif, #else, #endif#if, #elif, #else, #endif用于条件编译:#if 常量表达式1语句...#elif 常量表达式2语句...#elif 常量表达式3语句......#else语句...#endif#if和#else分别相当于C语句中的if, else. 它们根据常量表达式的值来判别是否执行后面的语句. #elif相当于C中的else-if. 使用这些条件编译命令可以方便地实现对源代码内容的控制.else之后不带常量表达式, 但若包含了常量表达式, gcc只是给出警告信息.使用它们可以提升代码的可移植性---针对不同的平台使用执行不同的语句. 也经常用于大段代码注释.e.g.#if 0{一大段代码;}#endif常量表达式可以是包含宏, 算术运算, 逻辑运算等等的合法C常量表达式, 如果常量表达式为一个未定义的宏, 那么它的值被视为0.#if MACRO_NON_DEFINED == #if 0在判断某个宏是否被定义时, 应当避免使用#if, 因为该宏的值可能就是被定义为0. 而应当使用下面介绍的#ifdef或#ifndef.注意: #if, #elif, #else之后的宏只能是对象宏. 如果name为名的宏未定义, 或者该宏是函数宏. 那么在gcc中使用"-Wundef"选项会显示宏未定义的警告信息.4, #ifdef, #ifndef, defined.#ifdef, #ifndef, defined用来测试某个宏是否被定义#ifdef name 或 #ifndef name它们经常用于避免头文件的重复引用:#ifndef __FILE_H__#define __FILE_H__#include "file.h"#endifdefined(name): 若宏被定义,则返回1, 否则返回0.它与#if, #elif, #else结合使用来判断宏是否被定义, 乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef. defined用于在一条判断语句中声明多个判别条件:#if defined(VAX) && defined(UNIX) && !defined(DEBUG)和#if, #elif, #else不同, #indef, #ifndef, defined测试的宏可以是对象宏, 也可以是函数宏. 在gcc中使用"-Wundef"选项不会显示宏未定义的警告信息.5, #include , #include_next#include用于文件包含. 在#include 命令所在的行不能含有除注释和空白符之外的其他任何内容.#include "headfile"#include#include 预处理标记前面两种形式大家都很熟悉, "#include 预处理标记"中, 预处理标记会被预处理器进行替换, 替换的结果必须符合前两种形式中的某一种.实际上, 真正被添加的头文件并不一定就是#include中所指定的文件. #include"headfile"包含的头文件当然是同一个文件, 但#include 包包含的"系统头文件"可能是另外的文件. 但这不值得被注意. 感兴趣的话可以查看宏扩展后到底引入了哪些系统头文件.关于#include "headfile"和#include 的区别以及如何在gcc中包含头文件的详细信息, 参考本blog的GCC笔记.相对于#include, 我们对#include_next不太熟悉. #include_next 仅用于特殊的场合. 它被用于头文件中(#include既可用于头文件中, 又可用于.c文件中)来包含其他的头文件. 而且包含头文件的路径比较特殊: 从当前头文件所在目录之后的目录来搜索头文件.比如: 头文件的搜索路径一次为A,B,C,D,E. #include_next所在的当前头文件位于B目录, 那么#include_next使得预处理器从C,D,E目录来搜索#include_next所指定的头文件.可参考cpp手册进一步了解#include_next6, 预定义宏标准C中定义了一些对象宏, 这些宏的名称以"__"开头和结尾, 并且都是大写字符. 这些预定义宏可以被#undef, 也可以被重定义.下面列出一些标准C中常见的预定义对象宏(其中也包含gcc自己定义的一些预定义宏:__LINE__ 当前语句所在的行号, 以10进制整数标注.__FILE__ 当前源文件的文件名, 以字符串常量标注.__DATE__ 程序被编译的日期, 以"Mmm dd yyyy"格式的字符串标注.__TIME__ 程序被编译的时间, 以"hh:mm:ss"格式的字符串标注, 该时间由asctime返回.__STDC__ 如果当前编译器符合ISO标准, 那么该宏的值为1__STDC_VERSION__ 如果当前编译器符合C89, 那么它被定义为199409L, 如果符合C99, 那么被定义为199901L.我用gcc, 如果不指定-std=c99, 其他情况都给出__STDC_VERSION__未定义的错误信息, 咋回事呢?__STDC_HOSTED__ 如果当前系统是"本地系统(hosted)", 那么它被定义为1. 本地系统表示当前系统拥有完整的标准C库.gcc定义的预定义宏:__OPTMIZE__ 如果编译过程中使用了优化, 那么该宏被定义为1.__OPTMIZE_SIZE__ 同上, 但仅在优化是针对代码大小而非速度时才被定义为1.__VERSION__ 显示所用gcc的版本号.可参考"GCC the complete reference".要想看到gcc所定义的所有预定义宏, 可以运行: $ cpp -dM /dev/null7, #line#line用来修改__LINE__和__FILE__.e.g.printf("line: %d, file: %s ", __LINE__, __FILE__);#line 100 "haha"printf("line: %d, file: %s ", __LINE__, __FILE__);printf("line: %d, file: %s ", __LINE__, __FILE__);显示:line: 34, file: 1.cline: 100, file: hahaline: 101, file: haha8, #pragma, _Pragma#pragma用编译器用来添加新的预处理功能或者显示一些编译信息. #pragma的格式是各编译器特定的, gcc的如下:#pragma GCC name token(s)#pragma之后有两个部分: GCC和特定的pragma name. 下面分别介绍gcc中常用的.(1) #pragma GCC dependencydependency测试当前文件(既该语句所在的程序代码)与指定文件(既#pragma语句最后列出的文件)的时间戳. 如果指定文件比当前文件新, 则给出警告信息.e.g.在demo.c中给出这样一句:#pragma GCC dependency "temp-file"然后在demo.c所在的目录新建一个更新的文件: $ touch temp-file, 编译: $ gcc demo.c 会给出这样的警告信息: warning: current file is older than temp-file如果当前文件比指定的文件新, 则不给出任何警告信息.还可以在在#pragma中给添加自定义的警告信息.e.g.#pragma GCC dependency "temp-file" "demo.c needs to be updated!"1.c:27:38: warning: extra tokens at end of #pragma directive1.c:27:38: warning: current file is older than temp-file注意: 后面新增的警告信息要用""引用起来, 否则gcc将给出警告信息.(2) #pragma GCC poison token(s)若源代码中出现了#pragma中给出的token(s), 则编译时显示警告信息. 它一般用于在调用你不想使用的函数时候给出出错信息.e.g.#pragma GCC poison scanfscanf("%d", &a);warning: extra tokens at end of #pragma directiveerror: attempt to use poisoned "scanf"注意, 如果调用了poison中给出的标记, 那么编译器会给出的是出错信息. 关于第一条警告, 我还不知道怎么避免, 用""将token(s)引用起来也不行.(3) #pragma GCC system_header从#pragma GCC system_header直到文件结束之间的代码会被编译器视为系统头文件之中的代码. 系统头文件中的代码往往不能完全遵循C标准, 所以头文件之中的警告信息往往不显示. (除非用#warning显式指明).(这条#pragma语句还没发现用什么大的用处)由于#pragma不能用于宏扩展, 所以gcc还提供了_Pragma:e.g.#define PRAGMA_DEP #pragma GCC dependency "temp-file"由于预处理之进行一次宏扩展, 采用上面的方法会在编译时引发错误, 要将#pragma语句定义成一个宏扩展, 应该使用下面的_Pragma语句:#define PRAGMA_DEP _Pragma("GCC dependency "temp-file"")注意, ()中包含的""引用之前引该加上转义字符.9, #, ###和##用于对字符串的预处理操作, 所以他们也经常用于printf, puts之类的字符串显示函数中.#用于在宏扩展之后将tokens转换为以tokens为内容的字符串常量.e.g.#define TEST(a,b) printf( #a "<" #b "=%d ", (a)<(b));注意: #只针对紧随其后的token有效!##用于将它前后的两个token组合在一起转换成以这两个token 为内容的字符串常量. 注意##前后必须要有token.e.g.#define TYPE(type, n) type n之后调用:TYPE(int, a) = 1;TYPE(long, b) = 1999;将被替换为:int a = 1;long b = 1999;(10) #warning, #error#warning, #error分别用于在编译时显示警告和错误信息, 格式如下:#warning tokens#error tokense.g.#warning "some warning"注意, #error和#warning后的token要用""引用起来!(在gcc中, 如果给出了warning, 编译继续进行, 但若给出了error, 则编译停止. 若在命令行中指定了 -Werror, 即使只有警告信息, 也不编译.【C语言中的预编译宏定义】。

c语言 define用法

c语言 define用法

c语言define用法C语言的宏定义(define)是一种预处理指令,用于为常量、函数和代码段定义符号常量。

宏定义是C语言的一个重要特性,可以提高代码的可读性和可维护性。

在本文中,我们将深入探讨C语言中宏定义的用法,包括其基本语法、参数的使用、注意事项以及一些实际应用案例。

一、基本语法C语言中宏定义的基本语法格式如下:#define 宏名替换文本其中,宏名指定要定义的宏名称,替换文本表示在程序中该宏名称出现时应进行的替换操作。

宏定义的作用是将所有的宏名的出现都替换为与之关联的替换文本。

以一个简单的例子来说明:#define PI 3.14在上述宏定义中,我们将宏名PI定义为3.14。

这意味着在后续的代码中,所有出现的PI都将被替换为3.14,起到了一个常量的作用。

二、参数的使用宏定义不仅可以定义常量,还可以定义带有参数的宏。

参数是宏定义中的变量,可以在宏替换时使用。

宏定义带参数的格式如下:#define 宏名(参数列表) 替换文本在替换文本中,可以使用参数来代替特定的数值或表达式。

下面是一个使用宏定义替换参数的例子:#define MAX(a, b) ((a) > (b) ? (a) : (b))在上述宏定义中,我们定义了一个名为MAX的宏,它带有两个参数a和b。

该宏定义的作用是返回两个值中较大的一个。

在后续的代码中,我们只需使用MAX(3, 5)即可得到较大的值。

三、注意事项在使用宏定义时,需要注意一些细节和陷阱。

首先,宏定义在预处理阶段进行替换操作,它只是简单地将宏名替换为对应的替换文本,并没有进行类型检查。

因此,需要确保宏定义的替换文本是合法的代码。

其次,宏定义中的参数是无类型的,只是简单地进行文本替换。

因此,在使用带有参数的宏定义时,需要注意括号的使用来保证正确的运算顺序。

还需要注意宏定义可能会带来的副作用。

例如,当宏定义包含有副作用的操作时,可能会导致意外的行为。

因此,在使用宏定义时,需要特别小心,并确保其行为符合预期。

C语言中的宏定义

C语言中的宏定义

C语言中的宏定义1. 简单宏定义简单的宏定义有如下格式:[#define指令(简单的宏)] #define 标识符替换列表替换列表是一系列的C语言记号,包括标识符、关键字、数、字符常量、字符串字面量、运算符和标点符号。

当预处理器遇到一个宏定义时,会做一个“标识符”代表“替换列表”的记录。

在文件后面的内容中,不管标识符在任何位置出现,预处理器都会用替换列表代替它。

不要在宏定义中放置任何额外的符号,否则它们会被作为替换列表的一部分。

一种常见的错误是在宏定义中使用 = :1.#define N = 100 /*** WRONG ***/2.int a[N]; /* 会成为 int a[= 100]; */在上面的例子中,我们(错误地)把N定义成一对记号(= 和100)。

在宏定义的末尾使用分号结尾是另一个常见错误:1.#define N 100; /*** WRONG ***/2.int a[N]; /* become int a[100;]; */这里N被定义为100和;两个记号。

在一个宏定义中,编译器可以检测到绝大多数由多余符号所导致的错误。

但不幸的是,编译器会将每一处使用这个宏的地方标为错误,而不会直接找到错误的根源——宏定义本身,因为宏定义已经被预处理器删除了。

简单的宏主要用来定义那些被Kernighan和Ritchie称为“明示常量”(manifest constant)的东西。

使用宏,我们可以给数值、字符和字符串命名。

1.#define STE_LEN 802.3.#defineTRUE 14.5.#defineFALSE 06.7.#definePI 3.141598.9.#defineCR '\r'10.11.#defineEOS '\0'使用#define来为常量命名有许多显著的优点:1) 、程序会更易读。

一个认真选择的名字可以帮助读者理解常量的意义。

否则,程序将包含大量的“魔法数”,使读者难以理解。

ifdef的使用方法与示例

ifdef的使用方法与示例

ifdef的使用方法与示例ifdef是C/C++中的一个条件编译指令,用于根据条件选择性地编译代码。

它在代码编译过程中起到了关键作用,能够使程序根据不同的条件进行自定义配置,提高代码的可维护性和可移植性。

本文将介绍ifdef的使用方法和示例,并探讨它在代码开发中的作用。

一、ifdef指令的基本语法ifdef指令的基本语法如下所示:#ifdef 宏名// 宏名存在时执行的代码块#else// 宏名不存在时执行的代码块#endif在这个语法中,首先判断给定的宏名是否已被定义,如果已定义,则编译#ifdef和#else之间的代码块;如果未定义,则编译#else和#endif之间的代码块。

这样,通过修改宏名的定义与否,我们可以选择性地编译特定的代码片段。

二、ifdef的使用方法和示例下面通过一个具体的示例来说明ifdef的使用方法。

假设我们在一个C语言项目中需要根据不同的编译平台进行代码适配。

我们可以定义一个名为“WINDOWS”的宏用于表示Windows平台,另一个名为“LINUX”的宏用于表示Linux平台。

在代码中我们可以根据定义与否来选择性地编译代码。

我们需要在Windows平台下执行特定的操作,而在Linux平台下执行另一种操作。

我们可以这样使用ifdef:#ifdef WINDOWS// Windows平台下的代码printf("This is Windows platform.\n");#else// 非Windows平台下的代码printf("This is non-Windows platform.\n");#endif在上述代码中,当定义了“WINDOWS”宏时,编译器会编译#ifdef和#else之间的代码块,即输出"This is Windows platform.";而当未定义“WINDOWS”宏时,编译器会编译#else和#endif之间的代码块,即输出"This is non-Windows platform."。

C语言三种预处理

C语言三种预处理
3.条件编译 定义:
当满足某条件时对一组语句进行编译,而条件不满足时则编译另一组语句。 形式:
#ifndef 标识符 程序段 1
#else 程序段 2
#endif 若标识符未被定义则编译程序段 1,否则编译程序段 2。 优点: 采用条件编译,可以减少被编译的语句,从而减少目标的长度。当条件编译 段比较多时,目标程序长度可以大大减少。
1.2 带参数的宏定义 格式:
#define 宏名(参数表) 字符串 举例:
#define S(a,b) ((a)*(b)) 说明:
①宏名和参数间不能有空格! ②宏替换只做替换,不做计算和表达式求解! ③宏展开不占程序运行时间只占编译时间! 掌握宏概念的关键在“替换”!
2.文件包含 由来:
文件包含处理在程序开发中会给模块化程序设计带来很大的好处,通过文件 包含的方法把程序中的各个功能模含处理是指在一个源文件中,通过文件包含命令将另一个源文件的内
容全部包含在此文件中。在源文件编译时,连同被包含进来的文件一同编译,生 成目标目标文件。 形式:
①#include "文件名"; 或
②#include <文件名>; 两种形式区别:
①系统首先在用户当前目录中寻找要包含的文件,若未找到才到包含目录中 去查找;
C 语言提供 3 种预处理功能:①宏定义②文件包含③条件编译。
0.预处理指令 预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第
一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。 整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某 些转换。
②系统在包含文件目录中去查找(包含目录由用户在设置环境时设置)而不 在源文件目录去查找。若文件不在当前目录中,双撇号内可给出文件路径。 说明:

c语言宏定义的语法要求

c语言宏定义的语法要求

c语言宏定义的语法要求在C语言中,宏定义是使用`#define`关键字进行的。

宏定义用于在程序中创建符号常量、函数宏和条件编译等。

以下是宏定义的语法要求:1. 符号常量的宏定义:```c#define IDENTIFIER value```- `IDENTIFIER` 是你为常量定义的名称。

- `value` 是该常量的值。

示例:```c#define PI 3.14159```2. 函数宏的宏定义:```c#define MACRO_NAME(parameters) replacement```- `MACRO_NAME` 是你为函数宏定义的名称。

- `(parameters)` 是函数宏的参数列表。

- `replacement` 是用于替换宏调用的代码。

示例:```c#define SQUARE(x) ((x) * (x))```3. 多行宏定义:```c#define MACRO_NAME \statement1; \statement2;```4. 条件编译宏定义:```c#ifdef MACRO_NAME// 代码块1#else// 代码块2#endif```5. 字符串化运算符:```c#define STRINGIZE(x) #x```这个宏允许你将传递给它的参数转换为字符串。

例如:```c#define HELLO_WORLD_STRING STRINGIZE(Hello World)```在上述例子中,`HELLO_WORLD_STRING` 将被替换为字符串"Hello World"。

6. 连接运算符:```c#define CONCATENATE(x, y) x ## y```这个宏允许你连接两个标识符。

例如:```cint xy = CONCATENATE(3, 4); // 将被替换为int xy = 34;```以上是宏定义的一些基本语法要求。

请注意,使用宏时要小心,确保在宏定义中使用括号来确保优先级正确。

编译预处理的三种形式

编译预处理的三种形式

编译预处理的三种形式编译预处理是指在编译阶段之前对源程序进行的一些处理,以便于编译器更好地理解和转换源程序。

这些处理包括宏定义、条件编译和文件包含等。

本文将分别介绍这三种形式的编译预处理。

一、宏定义宏定义是指用一个标识符来代表一段代码,然后在程序中使用该标识符来表示该段代码。

宏定义的语法如下:#define 标识符替换文本其中,标识符是一个由字母、数字和下划线组成的字符串,替换文本可以是任意合法的C语言代码。

1.简单宏定义简单宏定义是指只有一个替换文本的宏定义。

例如:#define PI 3.1415926这个宏定义将标识符PI替换为3.1415926。

在程序中使用该宏时,编译器会将所有的PI替换为3.1415926。

2.带参数的宏定义带参数的宏定义是指可以接受参数的宏定义。

例如:#define MAX(a, b) ((a) > (b) ? (a) : (b))这个宏定义可以接受两个参数a和b,并返回其中较大的值。

在程序中使用该宏时,需要传递两个参数,并且要用括号将每个参数括起来,以避免优先级问题。

3.带可变参数的宏定义带可变参数的宏定义是指可以接受可变数量参数的宏定义。

例如:#define PRINTF(format, ...) printf(format, ##__VA_ARGS__)这个宏定义可以接受一个格式化字符串和可变数量的参数,并将其传递给printf函数。

在程序中使用该宏时,需要传递至少一个参数,格式化字符串中使用%来表示要输出的数据类型,可变参数用逗号分隔。

二、条件编译条件编译是指根据不同的条件选择性地编译某些代码。

条件编译通常用于实现跨平台或调试功能。

1.#ifdef和#ifndef#ifdef和#ifndef分别表示“如果定义了某个宏”和“如果未定义某个宏”。

例如:#ifdef DEBUGprintf("debug mode\n");#endif这段代码只有在DEBUG宏已经被定义时才会被编译。

C语言之详解#ifdef等宏

C语言之详解#ifdef等宏

C语言之详解#ifdef等宏指令用途#空指令,无任何效果#include包含一个源代码文件#define定义宏#undef取消已定义的宏#if如果给定条件为真,则编译下面代码#ifdef如果宏已经定义,则编译下面代码#ifndef如果宏没有定义,则编译下面代码#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码#endif结束一个#if……#else条件编译块#error停止编译并显示错误信息这几个宏是为了进行条件编译。

一般情况下,源程序中所有的行都参加编译。

但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。

有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。

条件编译命令最常见的形式为:#ifdef标识符程序段1#else程序段2#endif它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。

其中#else部分也可以没有,即:#ifdef程序段1#denif这里的“程序段”可以是语句组,也可以是命令行。

这种条件编译可以提高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代替。

c语言条件编译用法

c语言条件编译用法

c语言条件编译用法条件编译是一种在C语言中使用的编译预处理指令,它允许程序在不同的条件下进行编译。

通过条件编译,我们可以根据不同的需求,在同一个源代码文件中编写适用于不同情况的代码。

这种灵活性使得条件编译成为C语言中一项非常重要的特性。

条件编译主要通过预定义宏来实现。

在程序中,可以通过`#define`指令来定义宏,而在条件编译中,宏的定义则可以通过指令`#ifdef`、`#ifndef`、`#if`、`#elif`和`#endif`来进行条件判断和控制。

下面,我们将介绍一些常用的条件编译指令的用法和注意事项。

首先,我们来看一下`#ifdef`指令。

`#ifdef`用于判断某个宏是否已经被定义。

如果该宏已经被定义,则执行它后面的代码;如果该宏未被定义,则编译器会忽略掉它后面的代码。

我们可以利用`#ifdef`来根据特定条件编写与之相对应的代码段。

例如:```cinclude <stdio.h>define DEBUG 1int main() {ifdef DEBUGprintf("Debug mode\n");endifprintf("Hello, World!\n");return 0;}```在上述代码中,当宏`DEBUG`被定义为1时,`#ifdef DEBUG`的条件为真,因此会输出`Debug mode`。

如果我们将`#define DEBUG 1`改为`#define DEBUG 0`,则`#ifdef DEBUG`的条件为假,输出`Debug mode`的代码段将被编译器忽略,只输出`Hello, World!`。

通过这种方式,我们可以方便地在调试和生产环境中切换代码的执行。

接下来,我们介绍一下`#ifndef`指令。

`#ifndef`与`#ifdef`的功能相反,它用于判断某个宏是否未被定义。

当该宏未被定义时,执行它后面的代码;当该宏已被定义时,编译器会忽略掉它后面的代码。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

6.指针
指针是一个特殊的变量,它里面存储的数值 被解释成为内存里的一个地址。
6.指针
6.指针
&操作符:取变量的地址 *操作符:对指针做解引用操作 int a=10; int *p=&a; //让指针p指向存储变量a的单元,
&a就表示是a单元的内存地址, //这个时候的*仅仅表示p是一个指针变量 printf("*p=%d a=%d",*p,a); //将打印出 *p=10,a=10,*p表示是对变量a做操作 *p=5; printf("*p=%d a=%d",*p,a); //将打印出*p=5,a=5
C语言基础知识
1、位操作 2、宏定义 3.ifdef条件编译 4.extern变量申明 5.结构体 6.指针 7.判断语句(if for switch case while 等)
1、位操作
2、宏定义
#define 标识符 字符串 #define SYSCLK_FREQ_72MHz 72000000
举例: Struct U_TYPE { Int BaudRate Int WordLength; }usart1,usart2;
定义: Struct 结构体名字 结构体变量列表 ;
5.结构体
结构体成员变量的引用方法是: 结构体变量名字.成员名
举例:usart1.BaudRate;
结构体指针变量定义也是一样的,跟其他变量 没有啥区别。 举例:struct U_TYPE *usart3; 结构体指针成员变量引用方法是通过“ ->” 符号实现,比如要访问 usart3 结构体指针指 向的结构体的成员变量 BaudRate,方法是: Usart3->BaudRate;
GPIOx->BSRR = GPIO_Pin; }
7.判断语句
if(表达式1)//表达式1条件为真 语句1 else if(表达式2)语句2 else 语句 n
7.判断语句
for(表达式1; 表达式2; 表达式 3) 语句 它的执行过程如下:先求解表达 式1。 求解表达式2,若其值为真(非 0),则执行for语句中指定的内 嵌语句,然后执行下面第3)步; 若其值为假(0),则结束循环, 转到第5)步。 求解表达式3。 转回上面第2)步继续执行。 循环结束,执行for语句下面的 一个语句。
7.判断语句
while语句的一般形式为: while(表达式) 语句
其中表达式是循环条件,语句为循环体
7.判断语句
switch(表达式){ case 常量表达式1: 语句1; case 常量表达式2: 语句2; … case 常量表达式n: 语句n; default: 语句n+1;
}
结合break使用
6.指针
指针作为函数参数:
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
/* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_PIN(GPIO_Pin));
Main.c 文件
//申明变量 id 是在外部定
u8 id;//只允许一次
义的,申明可以在很多个文
main()
件中进行
{
void test(void){
id=1;
id=2;
printf("d%",id);//id=1 }
test();
printf("d%",id);//id=2
}
5.结构体
声明结构体类型: Struct 结构体名{ 成员列表; };
3.ifdef条件编译
#ifdef 标识符Βιβλιοθήκη 程序段 1#else
程序段 2
#endif
举例:
#ifdef STM32F10X_HD
大容量芯片需要的一些
变量定义
#end
4.extern变量申明
extern u16 USART_RX_STA;
u16 USART_RX_STA;
test.c 文件
extern u8 id;
相关文档
最新文档