C的typedef声明与#预处理指令

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.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

/*标准函数库使用下划线作为前缀,自定义库可以去掉_前缀避免与库冲突;常用大写加下划线用来定义,避免头文件的重复包含;*/

猜你喜欢

转载自www.cnblogs.com/caesura-k/p/12363060.html