zoukankan      html  css  js  c++  java
  • C的声明与预处理指令

    1 typedef:给已有的类型声明新的名称,并不能创建新的数据类型;

      1.1 typedef 声明

    typedef unsigned char BYTE ;      /* 将 unsigned char 重新命名为BYTE ;*/
    typedef char * STRING ;           /*将 char * 声明为STRING */

      1.2 typedef与#define

    typedef char * STRING;
    STRING  name, course; //等价于 char * name , * course;
    
    #define STRING char * 
    STRING name, course;  //等价于 char * name, course; 
    
    /*1,typedef只能定义数据类型,而#define可以定义数据类型和值;*/
    /*2,typedef由编译器解释,而#define由预处理器解释;*/
    /*3,如果定义在函数外则具有文件作用域,函数内则局部作用域*/

      1.3 typedef与结构体

        1.3.1 为结构体类型声明一个简洁的名称

    typedef struct complex{
    float real;
    float imag;
    } COMPLEX;
    /* 将结构体类型 struct complex 声明为 COMPLEX; */

        1.3.2 typedef声明时,结构体类型可以省略原标识符,只保留struct标识符;

    typedef struct{
    float real;
    float imag;
    } COMPLEX;
    /*声明一个结构体类型名字为COMPLEX类型;*/
    
    COMPLEX x={3.1 ,4.0};
    /*初始化一个COMPLEX类型的变量x;*/

    2 #预处理指令 :预处理器一方面是包含一些程序所需的其他文件,一方面只进行替换替换,并不涉及计算;

      2.1 注释:程序在进入预处理器之前,需要先经过编译器处理注释,将每条注释用一个空格替代;

    int/*想不到我是一个空格吧?*/num;
    int num;

      2.2 #define:在函数中对宏名进行替换;

    #define TWO 2
    #define FOUR TWO*TWO     /* 替换之后是:2*2 */
    // 格式 :#define  宏 替换体
    //预处理指令并不是C指令,所以没有分号结尾;

        2.2.1 创建带参数的类函数宏;

    #define Byte0(data)          ((byte *)(&(data)))[0]        /*宏名为Byte0,参数为data*/
    #define Byte1(data)          ((byte *)(&(data)))[1] 
    #define Byte2(data)          ((byte *)(&(data)))[2]          
    #define Byte3(data)          ((byte *)(&(data)))[3]
    /* 相当于addr[0],addr[1],addr[2],addr[3],将原先存储着int型的地址,强制转换为byte型来存储,所以要声明4个指向byte型的指针;  */
    /* 目的大概是为了防止数据丢失,然后在不同位数的单片机上移植;或者是为了特定目的传输数据;*/

        2.2.2 创建带参数的宏,对参数的取值有范围要求时,可以用来判断参数取值是否符合要求;

    #define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || 
                                           ((SOURCE) == SysTick_CLKSource_HCLK_Div8))

          如果SOURCE的取值不是后面的两个宏,则IS_SYSTICK_CLK_SOURCE(SOURCE)等于0;

       2.3 #include:告诉预处理器 将被包含文件的所有内容输入到当前位置替换#include指令;

    #include<stdio.h>
    /*告诉编译器在标准目录(也就是库目录)下查找该文件;*/
    #include"system.h"
    /*告诉编译器先在当前.c文件所在目录下查找该文件,找不到再去库中查找;*/
    
    /*#include是预处理器的指令,但是<>和""是为了告诉编译器查找路径;*/
    /*程序大小是由编译器编译时生成的代码决定的,与是否包含大型头文件无关;*/

        2.3.1 头文件中的定义声明的包含问题:用static副本解决

    /*system.h文件如下*/
    static const double PI = 3.1415 ;
    static const months = 12 ;
    /*如果去掉static,将导致每个包含的C文件都有一个相同的定义式声明,这是不允许的;定义式声明只能声明一次,引用式声明可以多次;*/
    void sum(int a,int b);
    /*将函数原型,全局变量等放在头文件中,然后在其他多个文件中包含该头文件,就相当于给每个文件都提供了一个接口沟通 */
    /*如果头文件中含有定义式声明,那么前面需要加上一个static,这相当于给每个调用的文件一个单独的数据副本;*/
    
    /* fie1.c 部分文件如下*/
    #include<stdio.h>
    #include"constant.h"
    ...

      2.4 #undef:取消已有的预处理器指令;感觉用不上;

    #define SIZE 256;
    /*定义了一个宏SIZE,预处理器在文件中将其替换为256;*/
    #undef SIZE ;
    /*取消了宏SIZE的定义,预处理器在文件中不会将其替换了;*/

      2.5 #ifdef ...#else...#endif :告诉编译器执行或忽略某些代码块;

    #define SIZE
    #ifdef SIZE                  /*如果定义了SIZE,那么执行下面的两行defne*/
    #define MAX 1024    
    #define MIN 512
    #else                        /*如果没有定义SIZE,那么执行下面的那个include*/
    #include"math.h"
    #endif                       /*条件编译语句完*/

      2.6 #ifndef:用来防止多次包含同一个文件,相同的宏被重新定义;

    /*假设有math.h文件如下:*/
    #ifndef SIZE
    #define SIZE 512
    #endif
    
    /*当前文件为file1.h*/
    #define SIZE 10
    #include "math.h" 
    /*由于前面一行定义过了SIZE,所以在math.h中就不会再重新替换SIZE为100;*/
    /*那如果我把SIZE 10 放到math.h后面,SIZE的值是会改变,还是会报错呢??*/

        2.6.1常见用法

    /*假设当前文件为drive.h*/
    #ifndef DRIVE_H_
    #define DRIVE_H_
    .../*假装好多预处理指令*/
    #endif
    
    /*标准函数库使用下划线作为前缀,自定义库可以去掉_前缀避免与库冲突;常用大写加下划线用来定义,避免头文件的重复包含;*/
  • 相关阅读:
    单据存储过程
    C语言II博客作业04
    C语言II博客作业03
    C语言II博客作业02
    C语言II博客作业01
    学期总结
    C语言I博客作业09
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
  • 原文地址:https://www.cnblogs.com/caesura-k/p/12363060.html
Copyright © 2011-2022 走看看