分享

C语言知识总结,你还有哪块知识不懂吗(下)

 岐岐feng 2018-06-04

一、预处理指令

  • 所有预处理指令都是以#开头

  • 不带参数的宏定义

//宏名 值;#define//宏的变量名全部是大写,结尾不需要写分号#define COUNT 6//还可以取消宏的定义#undef COUNT
  • 编译器的作用是将原代码文件中的代码翻译成机器可执行的代码,也就是0和1,而预处理指令会在编译器翻译代码之前执行

  • 带参数的宏定义

/*一定要加括号,否则会出现意想不到的结果比如像下面这样调用 sum(10,10) * sum(10,10);相当于下面: 10+10*10+10 这样替换过后改变了运算顺序,也就改变了预期的运算结果 所以一定要把所有变量都加上括号 再比如平方的例子一定要像下面这样写,每个形参都要加上括号 #define Square(a)((a)*(a))*/#define sum(v1,v2)((v1)+(v2))int main(void){ int result = sum(11,10); printf('result=%d\n',result); //输出了21 return 0;}
  • 宏定义只是单纯的把左边的定义(比如:sum(v1,v2))替换成右边的(比如:(v1)+(v2)),不做任何运算

  • 在常见的比较简单的函数可以使用宏定义,这样比函数效率要高

  • 条件编译

#define A 10int main(){//条件编译判断如果用到常量值,比如下面的A//则必须得是通过宏定义的,因为在编译前已经进行了判断//条件的括号可以省略 #if (A == 10) printf('a = 10\n'); #elif (A == 5) printf('a = 5\n'); #else printf('a is other number\n'); #endif //一定要有#endif结尾 return 0;}
  • 防止文件多次被包含

当进行多文件开发时,某些函数功能,需要在.h文件中进行声明,还要将.h文件包含到某个文件中,当代码量过大时,有可能发生多次包含,这虽然不会产生错误,但是会影响性能,所以在头文件中可以利用条件编译,防止多次包含头文件,例如像下面这样定义头文件:

/*解释下面的写法的逻辑:如果没有定义宏 ABC 那么就定义一个宏ABC并且声明sum()函数如果第二次被包含时,同样会进行判断此时判断的条件不成立,因为第一次被包含时已经创建了宏变量ABC所以这样一来,避免了重复包含同一个头文件ABC宏名称不能和别的头文件中的冲突!所以一般使用当前.h头文件名称命名*/// #ifndef等同于#if !define,对应的有#ifdef 等同于 #if define#ifndef ABC// ABC一般写成当前头文件的名称,后面的值随便写 #define ABC 11 int sum(int,int);#endif
  • typedef

  • 定义类型的别名(一般是全局变量,方便被使用),使用typedef以后,会提高开发效率

  • 应用于5个场合

  1. 基本数据类型
  2. 指针
  3. 枚举
  4. 结构体
  5. 指向函数的指针
  • 应用于基本数据类型

//需要分号typedef int MyInt;int main(){ //声明别名后,可以这样定义int类型变量 MyInt i = 10;}
  • 应用于指针

//给指针类型起了一个别名Stringtype char* String;int main(){ String = “luoguankun”;}
  • 应用于结构体

//定义了一个结构体类型Studentstruct Student { int age;};//给结构体Student起了个别名叫做Mystutypedef struct Student MyStu;//或者像下面这样,在定义结构体类型的时候直接起别名,这样更加精简typedef struct Student { int age;}MyStu;//如果像上面这样给结构体起了别名,定义结构体变量就变成了下面这样:MyStu s1;MyStu s2;MyStu s3;//还有一种是没有类型名的结构体//下面的结构体不能使用原本的方式创建结构体变量//只能通过下面的方式创建结构体变量,无法用struct Student stu = {10};这种方式创建结构体变量,//而前面几种两种创建结构体变量的方式都可以//而这个只能像下面这样创建://MyStu stu;typedef struct { int age;}MyStu;
  • 应用于枚举类型

//以下是没有使用typedef定义别名时的枚举使用enum Sex {Man, Woman};enum Sex s = Man;//以下是使用typedef定义别名后的使用方法typedef enum Sex MySex;MySex s = man;//还可以在定义枚举类型的同时定义别名(推荐这样定义)typedef enum Sex {Man, Woman} MySex;MySex s1 = man;
  • 应用与指向函数的指针

//定义一个函数int sum(int a, int b){ return a+b;}//指向上面函数的指针声明和调用int (*p)(int, int) = sum;int result = p(10,20);//使用typedef为指向函数的指针定义别名typedef int (*MyPoint)(int, int);MyPoint p = sum;int result = p(20,20);
  • 简化指向结构体的指针

//简化前struct Person{ int age;}; struct Person p = {20}; struct Person *p2 = &p;printf('age = %d\n”, p2->age);//简化后typedef struct Person{ int age;} *PersonPoint;struct Person p = {20}; PersonPoint p2 = &p;printf('age = %d\n', p2->age);

C语言知识总结,你还有哪块知识不懂吗(下)

二、static和extern对函数的作用

  • 这两个关键字分别代表内部和外部函数

  • static —— 内部函数,只能被本文件访问,其他文件不能访问,但可以通过外部函数间接访问
  • extern —— 外部函数(默认)
  • 在多文件开发的情况下,不同文件中的外部函数不可以重名,内部函数可以同名,但在同一个文件中内外部函数都不能重名
  • 定义完整的外部函数需要在函数前加上extern关键字,也可以省略,因为它是默认的
  • 定义内部函数需要在函数前面加上static关键字
  • 虽然被static关键字修饰的函数不能被外部文件直接调用,但可以间接调用,在外部函数中调用内部函数(条件是要被间接调用的内部函数和外部函数在同一个文件),并且必须在外部函数的上面被声明

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多