c语言预处理指令、typedef、static和extern相关介绍

一:typedef 

   作用:可以给一个已经存在的数据类型取一个别名

 格式:typedef 原数据类型  新类型   例如:typedef   int  INT;

 预处理指令#define 也可以给数据类型取别用用法:  #define  INT  int;

//1、用在基本数据类型上
    int a = 10;
    typedef int TNT;
    typedef char CHAR;
    CHAR c='A';   //65
    TNT b = 100;
    
    //2、给数组起别名
    char ch[5];
    typedef char NAME[20];
    //用新的类型定义数组
    NAME a1,a2;  //char a1[20]  char a2[20]
    
    
    //3、用在结构体上
    //1)先定义结构,然后在定义新的类型
    struct iPhone iphone5;
    struct iPhone *p;
    
    typedef struct iPhone IPHONE;
    IPHONE iphone6;
    IPHONE *p1;
    
    
    //2)定义结构体的时候,重新定义为一个新的类型
    typedef  struct Car{
        int lunzi;
    }CAR;
    CAR car1;
    car1.lunzi = 80;
    printf("%d\n",car1.lunzi);
    
    //3)给一个匿名的结构体定义一个新的类型
    typedef struct{
    
        char *head;
        int data;
        char *next;
    
    }NODE;
    
    NODE h;
    
    
    //4、用在枚举类型上
    //1)给一个枚举类型定义一个新的名称
    typedef enum weekday{
       one,
        two
    }WEEK;
    
    WEEK day;
    day = one;
    
    //2)给一个匿名的枚举类型,定义一个新的名称
    typedef enum {
        three,
        four
    }WEEK1;
    
    WEEK1 day2;
    day2 = three;
    
    //3)用一个已经存在的枚举类型,定义一个新的类型
    enum iColor{jin,bai,hei};
    enum iColor c1;
    typedef enum iColor ICOLOR;
    ICOLOR c2;
    c2 = jin;
    
    
    //5、给函数指针起别名
    int (*p8)(int a,int b);
    p8 = sum;
    int s1 = p8(56,23);
    
    
    typedef int (*ADD)(int a,int b);
    ADD p9;
    p9 = max;
    s1 = p9(34,88);
    
    printf("%d\n",s1);
    
    gets(a2);
    puts(a2);

 

 

二 :预处理指令 

    1)以 “#”开头

    2)在编译之前做的一些处理 

  1>#include   文件包含指令    

    1)#include  <系统头文件>

    2) #include  "自定义头文件"   

  作用:包含了系统或者用户自己定义的函数的声明,程序编译不会报错或警告,跟程序链接没有关系

  完成了函数声明的拷贝。OC中不用#include因为它的头文件比较繁琐,还需要写条件编译指令(未来防止头文件的重复拷贝)

  

  2>#define 宏定义

    1】无参的宏定义:   #define 宏名  字符串

  注意:

   1)宏定义,后面不用加分号

   2) 当宏出现在字符串中的时候,不进行替换

   3) 宏替换:在源程序中所有出现宏名的地方都替换成 宏定义的字符串

   4) 宏定义的时候,注意一般情况下为了区分它和变量,一般是大写(棕色)

   5)宏定义一般写到文件的开头,作用域从定义开始,到文件结束

      如果提前碰到了 #undef 则宏就被取消了,下面的函数不能在使用宏了

  

#include <stdio.h>
//无参数的宏
#define COLS 5
#define ROWS 10
#define M 3*y+y*y
#define PI 3.14
#define ZC 2*PI*COLS

#define INT int
#define CAR struct Car

#define P printf
#define D "%d\n"
#define F "%f\n"

#define INT1 int *
typedef int* PINT;  //typedef要加分号

struct Car{

    int lunzi;
};

void test(){
    printf("%f\n",ZC);
}
//取消宏定义
#undef ZC

void test2(){

    //printf("%f\n",ZC);

}
int main(int argc, const char * argv[])
{
    //1、宏的基本用法
    printf("%d,%d\n",COLS,ROWS);
    
    //2、宏出现在字符串中
    char *str="Hello world!,COlS\n";
    printf(str);
    
    //3、宏替换
    int y = 4;
    //         28*3    +       28*28         -28
    //  s = 3*y+y*y*3+3*y+y*y*3*y+y*y-3*y+y*y;
    int s=0;
    s = (3*y+y*y)*3+(3*y+y*y)*(3*y+y*y)-(3*y+y*y);  //840
    s = M*3+M*M-M;
    printf("%d\n",s);   //284
    
    //4、使用的宏,其中又包含了其他的宏
    test();
    
    //5、用宏可以定义新的变量
    //int a
    INT a;
    a = 10;
    printf("a = %d\n",a);
    
    //struct Car car1={4};
    CAR car1 ={4};
    printf("lunzi  = %d\n",car1.lunzi);
    
    //6、可以妙用宏,简化输出的代码
    float f1 = 12.0f;
    P(D,a);
    P(F,f1);
    
    
    //7、关于typedef和#define的区别
    int c=2,d=5;
    
    //int *p,q;
    //p指针,q就是一个int型
    INT1 p,q;
    p = &c;
    q = &d;  //q是整型的
    
    //int *m;int *n;
    //int *m,*n;
    PINT m,n;
    m = &c;
    n = &d;

  2】有参的宏定义

  #define 宏名(形参列表) 字符串

     注意:

     1)在有参宏定义中,形参不需要指定类型

     2)多个参数使用逗号分隔

     3)有参宏定义的时候,注意宏名和括号之间不能有空格

 宏定义都是完成了替换工作,不参与运算

  3> 条件编译: 只编译满足条件的代码块条件编译:

    形式一:

    #if                 if

    #elif               else if

    #else               else

    #endif              }

    形式二:

    #ifdef M     //如果定义了  M 就编译语句块1,否则编译语句块2

        语句块1;

    #else

        语句块2;

    #endif

    形式三    

    #

三:利用条件编译打印调试信息

#include <stdio.h>
#define DEBUG1 1   //0 程序上线,不能打印调试信息,1 开发模式

#if DEBUG1==0
//          format 表示这是一个参数      ..可以多个参数
//                                    ##表示可以没有参数
#define Log(format,...) printf(format,## __VA_ARGS__)
#else
#define Log(format,...)
#endif

void test(){

    int a=10;
    Log("ssssss\n");

}


int main(int argc, const char * argv[])
{
    test();

    Log("xxxxx\n");
    return 0;
}

四:static 和extern的区别

一   extern对函数的作用
1> 完整的定义一个外部函数
2> 完整的声明一个外部函数
    (默认情况下函数都是外部函数所有extern可以省略)

static对函数的作用
1> 完整的定义一个内部函数
2> 完整的声明一个内部函数

二   static对全局变量的作用
static修饰的全局变量是内部变量  ,只能被本文件使用

三  static对局部变量的作用
而static修饰的局部变量会延长局部变量的生命周期,程序结束才会销毁,同时局部变量的作用域不会改变

四   static性能问题
static修饰的局部变量延长了它的生命周期,因此当一个函数被不断调用的话,其内部的局部常量内存中不会被不断分配销毁
五:static修饰的局部变量或全局变量在初始化前存在bss段,初始化后存放在数据段,

 

posted @ 2014-10-26 22:06  _boy  阅读(752)  评论(0编辑  收藏  举报