黑马程序员—C语言—预处理指令及补充

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


一、预处理指令

代码被编译之前运行的指令

分为宏定义、条件编译、文件包含

特点:

1)、所有的预处理指令都是以”#”开头;

2)、预处理指令在代码编译成01之前执行;

3)、预处理的位置是随便写的;

4)、预处理指令的作用域:从编写指令的那一行开始,一直到文件结尾。

1、宏定义:只是纯粹的文本替换

a、不带参数的宏定义

#define 宏名 字符串

使用注意:

(1)、宏名一般用大写字母或以K开头,以便与变量名区别开来,但小写也无语法错误;

(2)、对程序中用双引号括起来的字符串内的字符,不进行宏的替换操作;

作用:在编译预处理时,将源程序中的所有宏名替换成一定的字符串(常用定义常量); 例如:#define N 100

终止宏定义的作用域用:#undef宏名;

b、带参数的宏定义

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

#define sum(v1,v2) ( (v1) * (v2) )   //每个参数都要用()括起来,结果值也要有();

作用:在编译预处理时,将源程序中所有宏名替换成字符串,并且将字符串中的参数用宏名右边参数列表中的参数替换;

与函数的区别:

(1)、带参数的宏定义效率比函数高;

(2)、宏定义不涉及存储空间的分配、参数类型匹配、参数传递、返回值问题;

2、条件编译

a、概念:程序的其中一部分代码只有在满足一定条件时才进行编译,否则不参与编译(只有参与编译的代码最终才能被执行)

b、定义:只要写了#if在最后面必须加上#endif(条件判断从这个位置结束)

      基本用法:

                #if 条件1

执行程序1

      #elif 条件2

执行程序2

#else

执行程序3

#endif

c、#if#elif后面的条件一般判断宏定义,而不是变量,因为条件编译是在编译之前进行的,而变量是在运行时才产生的、才有使用的意义。

d、条件编译与if的区别:条件编译编译的时候只编译成立的条件语句;if是所有语句都进行编译。

e、#if defined (宏名) == #ifdef宏名判断定义宏

     #if !defined (宏名) == #ifndef宏名判断未定义宏

3、文件包含

#include <> #include “”

使用注意

1、<>表示系统自带的文件,””表示自定义的文件;

2、不允许循环包含;比如a.h包含b.h,b.h又包含a.h这是错误的

3、#include指令可能导致多次包含同一头文件,降低编译效率;可在头文件中加入#ifndef和#endif。

如;                   

#ifndef LISI_H

#define LISI_H

int sum(int a,int b);

#endif

typedef 

a、为各种数据类型定义一个新名字(别名)

b、使用场合:基本数据类型,指针,结构体,枚举,指向函数的指针,指向结构体的指针

(1)、基本数据类型

typedef int MyInt; 

typedef MyInt MyInt2;

(2)、指针

typedef char * string;// 给指针类型char *起一个新的类型名称String

(3)、结构体

1>struct Student

{

    int age;

};

typedef struct Student MyStu;

2>typedef  struct Student

{

    int age;

} MyStu;

3>typedef struct

{

    int age;

} MyStu;

(4)、枚举

1>enum Sex {Man,Women};

typedef enum Sex MySex;

MySex s = Man;

2>typedef enum Sex {Man,Women} MySex;  //Sex可忽略;

(5)、指向函数的指针

typedef int (*MyPoint) (int, int);// 别名就是MyPoint

int sum(int a, int b)

{

return a + b;

}

int minus(int a, int b)

{

return a - b;

}

int main()

{

MyPoint p = sum;

MyPoint p2 = minus;

return 0;

}

(6)、指向结构体的指针

1>

struct Person

{

int age;

}

typedef struct Person * PersonPoint;

int main()

{

struct Person p = {20};

PersonPoint p2 = &p;//相当于struct Person *p2=&p;

}

2>

                      typedef struct Person

                    {

                            int age;

} * PersonPoint;

int main()

{

struct Person p = {20};

PersonPoint p2 = &p;//相当于struct Person *p2=&p;

}

3、使用注意:

typedef#define在某些场合可以互换,但有些场合不能互换;例如:

typedef char * string;

string s1,s2; //相当于char *s1,*s2;

#define string char *

string s3,s4; //相当于char *s3,s4;

staticextern

1、函数分两种:

a、外部函数:定义的函数允许本文件和其他文件访问、调用;

b、内部函数:定义的函数不允许其他文件访问、调用,只能在本文件内部使用。

c、外部函数和内部函数的区别:

(1)、外部函数:默认情况下的所有的函数都是外部函数,不允许有同名的外部函数;

(2)、内部函数:允许不同文件中有同名的内部函数。

2static和 extern对函数的作用

a、extern对函数的作用:

(1)、完整的定义外部函数:extern void test(){}; //extern可以省略;

(2)、完整的声明外部函数:extern void test(); //extern可以省略;

b、static对函数的作用:

(1)、定义内部函数:static void test(){}; 

(2)、声明内部函数:static void test();

其他文件想调用test.c里的内部函数,可以在文件中先调用test.c的一个外部函数,用这个外部函数间接调用这个内部函数。

3staticextern对全局变量的作用

a、全局变量分两种:

(1)、外部变量:定义的变量允许本文件和其他文件访问、调用;

(2)、内部变量:定义的变量不允许其他文件访问、调用,只能在本文件内部使用。

(3) 、默认情况下的所有的全局变量都是外部变量;

(4)、不同文件中的同名外部变量都代表同一个变量;

(5)、内部变量的作用:不同文件中的同名内部变量互不影响。

b、定义一个外部变量:int a;

      定义一个内部变量:static int a;

c、static对全局变量的作用:定义内部变量;

d、extern对全局变量的作用:声明外部变量;

4static对局部变量的作用:

static修饰局部变量: static int b;

a、延长局部变量的生命周期,程序结束的时候,局部变量才会被销毁;

b、并没有改变局部变量的作用域;

c、所有的test函数都共享这一个变量b

#include <stdio.h>

void test()

{

int a = 1;

static int b = 1;

printf(“a = %d\n”,a++);

printf(“b = %d\n”,b++);

}

int main()

{

test();

test();

return 0;

}

输出结果是 a=1 b=1 a=1 b=2;

d、使用场合:

1)、如果某一个函数的调频率特别高;

2)、这个函数内部的某个变量值是固定不变的;

、递归

递归的两个条件:

1)、函数自己调用自己;

2)、必须有个明确的返回值;

设计一个函数,用来计算bn次方

int pows(int b, int n)

{

if( n < = 0) return 1;

return pows(b, n-1) * b;

}

int main()

{

int c = pows(3,5);

printf(“%d\n”,c);

return 0;

}


---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值