2019年7月16日星期二(C语言)

一、typedef关键词

1、什么是typedef?作用是什么?

typedef其实就是 type + define,给一种数据类型(基本数据类型/非基本数据类型)取一个新的别名。

例子: 给int这种类型取一个新的名字叫aaa。  -> 很少给基本数据类型取别名  1%

       给struct mydata这种数据类型取新的名字叫mydata。  -> 给非基本数据类型取别名  99%

作用: 简化复杂的数据类型。

2、如何使用typedef给数据类型取别名?

使用格式: typedef + 数据类型 + 新的名字

1)给int这种类型取一个新的名字叫aaa

typedef int aaa;   -> 原则来typedef后面的这个"int aaa"看看,类型是int,剩下的就是aaa就是它的新名字。

在后面的代码中,定义一个整型变量:aaa a;

 

例子:

#include <stdio.h>

int main()

{

       typedef int aaa; //int 等价于 aaa

       aaa a = 10;

       printf("a = %d ",a);

       return 0;

}

2)给struct mydata这种数据类型取新的名字叫mydata

typedef struct mydata{

       char name[20];

       int age;  

}mydata;  //struct mydata 等价于 mydata

 

mydata bbb;  -> 定义一个结构体变量。

二、linux GCC编译器编译过程。

1、一步到位:编译命令: gcc ***.c -o ***

                     GCC编译器

  高级语言       -------------------------->   二进制文件

   ***.c                              ***

2、细分每个编译过程,可以分为4个步骤。

  高级语言       预处理           编译            汇编            链接     二进制文件

   ***.c        ------>     ***.i   ----->  ***.s   ----->  ***.o   ------>      ***

1)这些步骤如何处理?

其实这些步骤都是gcc编译器的参数来的,我们只需要查询ubuntu即可。  -> man 1 gcc

-E  Stop after the preprocessing stage; do not run the compiler proper.  The output is in the form of preprocessed source code, which is sent to the standard output. //在预处理阶段之后就停止了,输出的文件***.i还是C语言文件。

-S  Stop after the stage of compilation proper; do not assemble.  The output is in the form of an assembler code file for each non-assembler input file specified. //在编译阶段之后就停止,不进行汇编,输出的文件***.s是汇编文件。

-c  Compile or assemble the source files, but do not link.  The linking stage simply is not done.  The ultimate output is in the form of an object file for each source file. //在汇编阶段之后就停止了,但是不进行链接,输出的文件***.o是二进制文件。

2)举实例。

准备高级C语言: hello.c

预处理: 把程序中头文件、条件编译、宏定义处理。

        gcc hello.c -o hello.i -E       hello.i: C语言文件

编译:检查程序中语法是否正确

      gcc hello.i -o hello.s -S         hello.s: 汇编文件

汇编: 将程序地址重新排列

       gcc hello.s -o hello.o -c        hello.o: 二进制文件

链接: 链接某些特定的库文件(标准C库、线程库..)

       gcc hello.o -o hello             hello:  二进制文件(可执行)  

三、自定义头文件

1、 自定义头文件中可以写什么内容?

包含系统的头文件: #include <stdio.h>

进行一系列函数声明: int fun(int x,int y);

宏定义: #define

结构体声明:

struct mydata{

       xxx;

       yyy;

}

2、自定义头文件格式

1)文件后缀: ****.h

2)将.c文件中系统的头文件、函数声明、宏定义、结构体声明等全部写入到头文件head.h

#ifndef _HEAD_H_   -> 如果没有定义_HEAD_H_

#define _HEAD_H_   -> 那么就定义_HEAD_H_

/* 系统头文件 */

#include <stdio.h>

/* 结构体声明 */

struct mydata{

       int a;

       char b;

};

/* 函数声明 */

int fun(int x,int y);

/* 宏定义 */

#endif   -> 结束定义

3)只需要在.c文件中包含头文件即可。

#include "head.h"

3、使用""<>包含头文件有什么区别?

1)使用#include <xxxx.h>只会去系统头文件路径下寻找xxxx.h,如果找不到,就会提示xxxx.h找不到。

  #include <head.h>  -> 编译出错:head.h: No such file or directory

解决方案:使用GCC编译器参数: -I 头文件的路径  (GCC编译器还会去这里寻找头文件)

         gcc hello.c -o hello -I .

 

2)使用#include "xxxx.h"会先去系统的头文件中寻找,如果找不到,就去该头文件包含的所在路径下找,如果还找不到,就会提示xxxx.h找不到。

  #include "stdio.h"  -> OK

  #include "head.h"   -> 先在系统路径下找,找不到则在当前目录下找,找到了就OK。

四、宏定义

1、 宏定义是什么?   -> 就是一个简单的替换。

其实宏定义与枚举类型非常相似,都是可以使用某些常量变得有意义,宏定义除了可以替换int类型,还可以是字符/字符串...

2、 宏定义处理的时间?

发生了编译的预处理阶段,而不是在运行时间。

3、 宏定义如何写?

1)无参宏

#define OK 0   -> OK 等价于 0

#define ERROR -1

#define MUSIC "xxx.mp3"

实例:

#include <stdio.h>

#define OK 0

int main()

{

       int a = 0;

       if(a == OK)

              printf("helloworld! ");

       return 0;

}

预处理阶段之后:

stdio.h已经展开

宏定义OK已经替换

int main()

{

       int a = 0;

       if(a == 0)

              printf("helloworld! ");

       return 0;

}

2)带参宏

#define XYZ(a,b) a*b

int ret = XYZ(10,20);

ret=10*20=200;

int ret = XYZ(10+10,20);

ret=10+10*20=210

4、注意的事项

1)宏定义只是发生了预处理阶段,占用预处理时间,不占用运行时间。

2)宏定义既可以使用大写字母组成,也可以使用小写字母组成。

五、条件编译?

1、 什么是条件编译?

根据条件的真假来编译代码,与注释类似的!

#if 1   -> 代表在endif之前的代码都需要编译!

       printf("appletree! ");

#endif

2、实例

#include <stdio.h>

int main()

{

#if 1

       printf("appletree! "); //大家好才是真的好

#endif

#if 0

       printf("helloworld! ");

#endif

}

以下的内容会在预处理阶段全部删除!

#if 0

       printf("helloworld! ");

#endif

//大家好才是真的好

六、关于预处理阶段细节问题

1、由于头文件中有函数声明,所以头文件必须在函数调用之前必须声明。

2、宏定义#define  头文件#include  条件编译#if  都是以#开头。

3、如果在同一行出现多个预处理语句,只会执行第一个预处理语句。

   警告:warning: extra tokens at end of #include directive

.多个.c文件的拆分

实例:

1、头文件:包含系统头文件、宏定义、函数声明、结构体声明。

#ifndef _HEAD_H_

#define _HEAD_H_

#include <stdio.h>

#define OK 0

typedef struct mydata{

       int a;

       int b;     

}mydata;

int fun(int x);

#endif

2、包含main函数在内的.c   -> 一般main.c里面只有main函数

#include "head.h"

int main(int argc,char *argv[])

{

       int a = 100;

       mydata A;

       A.a = 10;

       A.b = 20;

       int x = fun(a);

       if(x == OK)

              printf("helloworld! ");

       my_fun(A);

#if 1

       printf("appletree! ");

#endif

       return 0;

}

3、功能函数1

#include "head.h"   -> 每一个功能函数都需要包含头文件。因为功能函数也使用printf()函数!

 

int fun(int x)

{

       printf("x = %d ",x);

       return x;

}

4、功能函数2

#include "head.h"

int my_fun(mydata B) // B = A

{

       printf("B.a = %d ",B.a);

       printf("B.b = %d ",B.b);

       return 0;

}

原文地址:https://www.cnblogs.com/zjlbk/p/11195555.html