1.条件编译可以在编译的时候从几组语句中选择一组编译而忽略其它组。
#ifdef/#ifndef...#else...#endif
这个结构可以根据一个宏名称是否被定义过从两组语句中选择一组编译。
最开始的预处理指令应该从两个里选择一个,不论选择哪个都应该在后面写一个宏名称。
如果最开始的预处理指令选择#ifdef就表示后面的宏名称被定义的时候编译前一组语句,否则编译后一组语句。
如果最开始的预处理指令选择#ifndef效果和#ifdef刚好相反。
例子:#infdef
运行结果:
直接编译结果:
在编译的时候使用gcc -D编译(gcc -D是使用gcc编译时用来定义宏的)
例子:#infnef
运行结果:
直接编译结果:
在编译的时候使用gcc -D编译(gcc -D是使用gcc编译时用来定义宏的)
练习:
#include <stdio.h>
int main(){
int order = 0;
printf("请点菜:");
scanf("%d",&order);
#ifdef ZHAOBENSHAN
if(order == 2){
printf("真没有\n");
}
else{
printf("没有\n");
}
#else
if(order == 2){
printf("没有\n");
}
else{
printf("有\n");
}
#endif
return 0;
}
运行结果:
2.#if..#elif(任意多次)...#else...#endif
以上结构也可以实现条件编译效果,它可以根据任意逻辑表达式从多组语句中选择一组编译。
#if和#elif后都需要写逻辑表达式,这些逻辑表达式里可以使用任意逻辑操作符。这些逻辑表达式的作用和if分支里的逻辑表达式的作用一样。
例子:
#include <stdio.h>
int main(){
#if defined(JINGPIN) // defined检查某一个变量或者名称是否存在,将值转换为bool值进行判断
printf("120%%\n");
#elif !defined(JINGPIN) && !defined(GONGCHANG)
printf("100%%\n");
#else
printf("80%%\n");
#endif
return 0;
}
运行结果:
3.多文件编程的时候任何一个函数只能属于一个文件,一个文件里可以包含多个函数。
多文件编程基本步骤:
(1)把所有函数分散在多个不同的源文件里。(主函数通常单独占一个文件)
(2)为每一个源文件编写配对的以.h作为扩展名的头文件(主函数所在的源文件不需要配对的头文件)只有不分配内存的内容都可以写在头文件里,头文件里至少应该包含配对源文件里的所有函数声明。
(3)修改所有源文件。在源文件里使用#include预处理指令包含必要的头文件。(配对头文件时必要头文件,如果源文件里使用了某个头文件里声明的函数则,这个头文件也是必要头文件)
编译多文件程序的时候需要在gcc命令后列出所有源文件的路径。
例子:多文件编程演示
步骤一:编写一个文件名05add.c的文件,里面的内容如下:
步骤二:编写一个文件名为 05add.h的文件,里面的内容如下:
步骤三: 编写一个05main.c的主函数,加入头文件05add.h,使用双引号包含05add.h文件,表示从当前目录开始查找文件。
步骤三:打开05add.c文件加入05add.h头文件
步骤四:编译方法:在gcc命令后列出所有源文件的路径
可以把多文件程序的编译过程记录在Makefile文件里,然后使用make工具根据Makefile文件的内容进行编译。
例子:编译Makefile文件,语法:vi Makefile
打开文件以后,输入以下内容: 注意:第二排,第五排,第八排gcc前面的空格是直接按teb键,不是按空格键
编译结果:输入make然后屏幕输出以下语句就可以使用./a.out进行编译了
Makefile里每个编译命令前都应该用tab键而不是空格。
头文件内容应该被包含在条件编译的预处理指令中间,这样可以避免编译的时候反复多次重复编译同一个头文件的内容。
第一个预处理指令必须是#ifndef
头文件使用的宏名称应该根据文件名称变化得到。
例子:
练习:多文件编程练习
步骤一:先创建一个06read.c文件
在06read.c文件中输入以下内容:
步骤二:创建一个名为06read.h的文件
在文件 06read.h中输入:
步骤三:创建一个06main.c的文件,然后输入以下内容:
步骤四:打开06read.c文件 ,添加两个头文件
步骤四:编写一个Makefile文件
在文件中加入以下内容:
步骤五: 编译Makefile.06文件
运行结果:
如果希望从一个源文件里使用另外一个源文件里声明的全局变量就需要使用extern关键字再次声明这个全局变量。
这种使用ectern关键字声明变量的语句不会分配内存,它们通常写在头文件里。
例子:将上面创建的06read.h、06read.c、06main.h三个文件复制为:07read.h、07read.c、07main.h
打开07read.c文件:
修改成下面的内容:
修改07read.h文件:
修改07main.c 文件:
删除07main.c里面的extern声明语句,直接将extern声明的变量放在07read.h文件里,好处是将声明语句放在头文件里,源文件就可以不用声明而直接使用这个变量。
不可以跨文件使用静态全局变量
例子:将num变量修改为静态变量编译错误
运行结果:
4. C语言里可以在一个存储区里记录多个数字
这种存储区的类型叫结构体类型,这种类型需要创建出来后才能使用。
结构体类型的存储区里包含多个子存储区,每个子存储区可以用来存放一个数字。
结构体的不同子存储区类型可以不同,甚至存储区也可以是结构体类型的存储区。
结构体声明语句可以用来创建结构体类型。
声明结构体类型的时候需要使用struct关键字。
例子:
结构体声明语句里包含多个变量声明语句,这些变量叫做结构体 的成员变量。
每个成员变量代表一个子存储区。
成员变量的声明语句不会分配内存,它们只是用来表示子存储区的类型和名称。
C语言里结构体不可以包含函数,C++可以。
结构体声明语句可以写在任何地方,包括头文件里。
例子:
可以把结构体作为类型声明变量,这种变量叫做结构体变量。
把结构体作为类型的时候需要把struct关键字和结构体名称一起作为类型名称使用。
例子:结构体变量声明语句:
结构体变量分配了内存,它们可以用来记录数字。
typedef关键字可以用来给一个数据类型起别名,别名可以用来代替原有的类型名称。
通常会给结构体类型起别名。
例子:使用typedef起别名
可以把声明结构体的语句和起别名的语句合并成一条语句。
这个时候可以省略结构体本身的名称。
例子:
声明结构体变量的时候也应该进行初始化
结构体变量的初始化方法和数组的初始化方法一样。
结构体变量通常不能作为整体使用,一般一次只能使用其中的某个子存储区。
以下写法可以用来表示结构体的某个子存储区。
prsn.age
其中prsn是结构体变量的名称,age是某个成员变量的名称。
例子:
运行结果:
同类型结构体变量之间可以直接赋值。
练习:
#include <stdio.h>
#include<string.h>
typedef struct {
int age;
float height;
char name[10];
}sperson;
int main(){
sperson prsn1={20,1.72f,"abc"};
sperson prsn2={0};
printf("请输入年龄:");
scanf("%d",&(prsn1.age));
printf("请输入身高:");
scanf("%g",&(prsn1.height));
printf("请输入姓名:");
scanf("%s",&(prsn1.name));
if(strlen(prsn1.name) == 9 && prsn1.name[8] != '\n'){
scanf("%*[^\n]");
scanf("%*c");
}
printf("年龄是%d\n",prsn1.age);
printf("身高是%g\n",prsn1.height);
printf("姓名是%s\n",prsn1.name);
prsn2=prsn1;
printf("年龄是%d\n",prsn2.age);
printf("身高是%g\n",prsn2.height);
printf("姓名是%s\n",prsn2.name);
return 0;
}
结构体指针用来记录结构体存储区的地址。
以下写法可以通过结构体指针表示结构体的子存储区:
p_person->age
其中p_person是结构体指针,age是成员变量名称。
例子:
#include <stdio.h>
#include<string.h>
typedef struct {
int age;
float height;
char name[10];
}sperson;
int main(){
sperson prsn1={20,1.72f,"abc"};
sperson prsn2={0};
sperson *p_person=NULL;
printf("请输入年龄:");
scanf("%d",&(prsn1.age));
printf("请输入身高:");
scanf("%g",&(prsn1.height));
printf("请输入姓名:");
scanf("%s",&(prsn1.name));
if(strlen(prsn1.name) == 9 && prsn1.name[8] != '\n'){
scanf("%*[^\n]");
scanf("%*c");
}
printf("年龄是%d\n",prsn1.age);
printf("身高是%g\n",prsn1.height);
printf("姓名是%s\n",prsn1.name);
prsn2=prsn1;
printf("年龄是%d\n",prsn2.age);
printf("身高是%g\n",prsn2.height);
printf("姓名是%s\n",prsn2.name);
p_person=&prsn1;
printf("年龄是%d\n",p_person->age);
printf("身高是%g\n",p_person->height);
printf("姓名是%s\n",p_person->name);
return 0;
}