zoukankan      html  css  js  c++  java
  • C语言第十一回合:预处理命令的集中营

    C语言第十一回合:预处理命令的集中营

     

    【学习目标】

     

    1.         宏定义

    2.         文件包括”处理

    3.         条件编译

    预处理命令:能够改进程序设计的环境。提高编程效率。

    其功能主要有三种:宏定义、文件包括、文件编译。

    ANSI标准定义的C语言预处理指令预览表



    A: 宏定义

    a不带參数的宏定义

    格式:#define标识符 字符串

    如:#define PI 3.1415926

    *标识符被称为:宏名

    *在预编译时将宏名替换成字符串的过程为:宏展开。

    *#define 是宏定义命令
    //求圆周长
    #include <stdio.h>
     
    #define PI 3.1415926
     
    int main( void )
    {
             float r;  //半径
             float c;  //周长
            
             r= 3.0;
            
             c= 2* PI* r;  //求圆周长
            
             printf("%.3f
    ", c );  //保留3为小数
            
             return 0;
    }
     


    PS:

    (1) 宏名一般为大写字母表示,便于差别。但也能够是小写的

    (2)使用宏名替换能够降低代码量。易于维护

    (3) 宏定义不是C语句。所以不必在末尾加分号。假设加了分号,会宏名会替代字符串和分号

        #define NUM 123;  //有分号。编译器会报错!!

    (4)      能够用#undef命令中止宏定义的作用域。否则其作用域由開始定义本文件结束。

    //#undef的使用
    #include<stdio.h>
     
    int main( void )
    {
             #define N 20   //N替代20
            
             printf( "%d
    ", N );
            
             #undef N   //结束N的作用域。假设没有这条语句提示redefined
            
             #define N 30   //N替代 30
            
             printf( "%d
    ", N );
            
        return 0; 
    }


    (5)宏定义时,能够引用已定义的宏名,能够层层置换

    如:

    #include<stdio.h>
     
    #define R 3.0
    #define PI3.1415926
    #define C2*PI*R
    #define SPI*R*R
     
    int main( void)
    {
             //打印圆的半径R。周长C,面积S
             printf( "R= %.2f
    ", R );
             printf( "C= %.2f
    ", C );
             printf( "S= %.2f
    ", S );
            
             return 0;
    }


    (6)对于程序中有“”(双撇号括)括起来的字符串内的字符,即使与宏名同样,也不进行置换。

    如:

    #include<stdio.h>
     
    #define stringhello,world!
    #define STRING"hello,world!"
     
    int main( void )
    {
             printf( "string" );  //string没有被替换为hello,world!
            
             putchar( '
    ' ); //换行
              
             printf( STRING );    //被替换为hello,world!
            
             return 0;
    }

    执行结果:

    string

    hello,world! 

     

    (7)      宏定义有别于变量的定义。宏定义仅仅做字符替换,不分配存储空间

    b 带參数的宏定义

    作用:进行參数的替换

    格式:#define宏名(參数表)  字符串

    [ 1 ]ADD带參数的宏

    #include <stdio.h>
     
    //带參数的宏替换
    #define ADD( a, b ) ( (a)+ (b) ) //每一个变量使用括号是防止替换后有歧义
     
    int main( void )
    {
             int n= 10;
             int m= 20;
        int sum= 0;
            
             sum= ADD( n, m );
            
             printf( "%d
    ",sum );
            
        return 0; 
    }


    [ 2 ]SIZEOF带參数的宏替换。

    能够求数组的长度(记住sizeof的使用有限制!)

    /*
    使用说明:
        strlen()函数仅仅能求字符串的长度
             sizeof不能求作为传递參数的数组原本的大小
    */
    #include <stdio.h>
     
    //定义SIZEOF宏
    #define SIZEOF( array) ( sizeof( array )/ sizeof( array[ 0 ] ) )
     
    int main( void )
    {
             int num= 0;
             int array[]= { 1, 2,3, 3, 7, 22, 33, 44, 5, 5, 6, 7, 10 };
     
             num= SIZEOF( array );
             printf( "array的长度为%d
    ",num );
            
        return 0; 
    }

    执行结果:

    array的长度为13

    PS:

    (1)     对于带參数的宏,按从左到有进行置换。假设字符串中的字符不是參数字符(如a+ b中的+)要保留。

    (2)      在宏定义的宏名与參数的括号之间不能加空格,否则会被当作字符串的一部分

    注意:函数与宏的差别

    (1)     使用宏的次数多时,宏展开后程序的长度会增长;而函数的调用不会。

    (2)     宏的替换不占用执行时间。仅仅占用编译时间。而函数则占用执行时间(即分配单元、值传递、返回等)

           

    B: 文件包括处理

    “文件包括”处理:一个源文件能够将另外一个源文件的所有包括进来。

    格式:(a)#include“文件名称”

             (b)#include <文件名称>

    两种格式的差别:使用尖括号表示在包括文件(即库文件)文件夹中去查找(包括文件夹是由用户在设置环境时设置),而不在源文件文件夹去查找;使用双引號则表示首先在当前的源文件文件夹中查找,若未找到才到包括文件夹(库文件)中去查找。

    PS:

    (1)  一个#include命令仅仅能包括一个源文件,多个源文件要多个#include的命令

    (2)    假设文件1要包括文件2,而文件2要包括文件3,则能够在文件1中用两个#include命令分别包括文件2和文件3,并且文件3必须出如今文件2前。

    (3)  文件包括能够嵌套使用。即一个包括文件能够包括一个被包括的文件

    (4)  被包括文件(file2.h)与其所在的文件(即用#include命令的源文件file2.c),在预编译后已成为同一个文件(而不是两个文件)。因此,假设file2.h中有全局静态变量,它也在file1.h文件里有效,不必用extern声明。

    C:条件编译

       条件编译:是对部分内容指定编译的条件,是其满足一定条件才进行编译。

    格式:

    (1)      

    #ifdef  标识符

       程序段1

    #else

       程序段2

    #endif

    作用:假设标识符被#define定义过,就进行程序段1的编译;反之对程序段2进行编译。假设没有程序段2,能够对#else省略。

    #include<stdio.h>
     
    #define R3.0   //定义R
     
    int main(void )
    {
                #ifdef R  //相似于if-else
               
                printf( "已经定义了R
    ");
               
                #else   
               
                printf( "未定义R
    ");
               
                #endif  //条件推断结束
               
                return 0;
    }

    (2)

         #ifndef 标识符 

    程序段1

    #else

        程序段2 

        #endif

    作用:假设标识符没有被#define定义过,则对程序段1进行编译;反之对程序段2进行编译。

    (3)

       #if 常量表达式

    程序段1

       #else 

        程序段2

       #endif

    作用:假设表达式的值为真(即非0)。则就对程序段1进行编译。反之对程序段2进行编译。

    #include <stdio.h>
     
    #define R 3.0   //定义R
     
    int main( void )
    {
             #ifndefR  //相似于if-else
            
             printf("未定义了R
    " );
            
             #else   
            
             printf("已经有定义R
    " );
            
             #endif  //条件推断结束
            
             return0;
    }

    【指尖的微笑】错误在所难免,希望得到大家的指正^-^

    转载时保留原文的链接http://oursharingclub.joinbbs.net/http://blog.csdn.net/mirrorsbeyourself

  • 相关阅读:
    int和bigint的区别
    mysql 的存储引擎介绍
    js-DOM ~ 04. BOM:浏览器对象模型window. 、定时器、在线用户、祝愿墙、BOM的内置方法内置对象
    github初学者搭建自己的网站
    JS-DOM ~ 03. 子节点的操作、style.样式和属性、dom元素的创建方法及操作、14个例题、主要是利用js直接控制html属性
    JS-DOM ~ 02. 隐藏二维码、锁定、获取输入框焦点、for循环为文本赋值、筛选条件、全选和反选、属性的方法操作、节点的层次结构、nodeType
    JS-DOM ~ 01. 了解DOM,动手做一下就明白了!/鼠标事件(好吧 其实我卡了三天
    javascript 数组的部分常用属性用法
    javascript . 05 json的组成、for...in 遍历对象、简单数据类型与复杂数据类型的传值与传址、内置对象
    javascript . 04 匿名函数、递归、回调函数、对象、基于对象的javascript、状态和行为、New、This、构造函数/自定义对象、属性绑定、进制转换
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/6754226.html
Copyright © 2011-2022 走看看