C语言第六天
1 函数的定义和使用
返回值类型 函数名称(形式参数列表)
{
函数代码;
return 返回值;
}
函数的作用:通常我们有一个有名字的函数代替一段代码。
1 能够具有复用性(重复的使用已经定义好的代码)。
2 能够将功能进行拆分,使得程序的编写更具有逻辑性。
2 局部变量和全局变量
局部变量:定义在函数内部的变量。只在{}内是有效的。
全局变量:定义在函数外部的变量。可以被所有的函数所共用。
int main()
{
int a = 10;
if (a>=10)
{
int b = 20;
printf("%d", b);
}
//for循环第一条语句定义的变量,属于for的复合语句
//在for的外面,无法使用
//如果说渐变量还想在后面继续使用,应该定义在for之前
int i = 0;
int j = 0;
for (int i = 0; i < 100; i++,j++)
{
j++;
printf("%d", i);//当作用域较大的变量和作用域较小的变量重名的时候
//在小作用域内使用的是自己作用域的变量。
}
if (i==100)
{
}
//printf("%d", b);不能使用
printf("%d", a);
return 0;
}
3 extern的作用
声明一个变量 声明了之后,就可以使用。
extern的作用也可以认为是 后面的变量不是在我这里定义的,请编译器去别的地方找到它。
在我们声明或者定义变量函数的时候,经常会出现这样的一个错误:
出现这样的错误,就说明:
a 只有声明,没有实现。
b 声明和实现不匹配。
4 static的作用
修饰全局变量或者函数的时候: 隐藏的作用,此全局变量或者函数只能在本文件中使用
修饰局部变量的时候:静态的作用,离开函数时,依然保留数值不销毁,下次函数使用上一次保留的值。
5 const的使用
const int a =10;
const类型的常量必须初始化。
int main()
{
const int num = 100;
//const int num1;必须有初始值
return 0;
}
6 指针的基本使用
1 定义指针变量
2 给指针变量赋值
3 解引用
int main()
{
int nNum = 100;
int nNum2 = 100;
int * p = NULL;
p = &nNum;//指针变量存储了谁的地址,它就指向了谁
*p = 200;//解引用,访问指向的位置
printf("%d\n", nNum);
p = &nNum2;
printf("%d\n", *p);
scanf_s("%d", p);
//scanf_s("%d", &(*p));//和上面的语句一样的
printf("%d", nNum2);
return 0;
}
关于结构体:
如果说,我们实现了一个学生系统,要存储学生的信息。那么如果和一名学生有关的信息,都是单独的去定义变量的话,那么维护起来,就会比较麻烦。
我们有一个简单的方法能够解决这样一个问题。
int main()
{
int nAge1 = 18;
double dHeight1 = 175.5;
int nSocore1 = 98;
int nAge2 = 20;
double dHeight2 = 168.5;
int nSocore2 = 95;
int nAge3 = 20;
double dHeight3 = 168.5;
int nSocore3 = 95;
int nAge4 = 20;
double dHeight4 = 168.5;
int nSocore4 = 95;
int nAge5= 20;
double dHeight5 = 168.5;
int nSocore5 = 95;
int nAge6 = 20;
double dHeight6 = 168.5;
int nSocore6 = 95;
return 0;
}
这种语法就是结构体,以下是结构体变量的基本用法:
int main()
{
//定义结构体变量
struct {
char szName[20];
int nAge;
double dHeight;
int nScore;
int nGender;
}stcXiaomingInfo;
//使用结构体变量,是通过.来访问结构体中的成员(字段)的
//使用某一个成员的时候,它是什么类型,就按照什么类型来使用
strcpy_s(stcXiaomingInfo.szName, 20, "xiaoming");
stcXiaomingInfo.nAge = 18;
stcXiaomingInfo.dHeight = 175.5;
stcXiaomingInfo.nGender = 1;
stcXiaomingInfo.nScore = 98;
//结构体变量的初始化
struct {
char szName[20];
int nAge;
double dHeight;
int nScore;
int nGender;
}stcXiaohongInfo = {"xiaohong",20};
struct {
char szName[20];
int nAge;
double dHeight;
int nScore;
int nGender;
}stcXiaoheiInfo = { "xiaohei",20 };
return 0;
}
按照如上的方式使用结构体,比较麻烦。定义结构体变量有简单的方法:
struct STUINFO{ //STUINFO是类型名
char szName[20];
int nAge;
double dHeight;
int nScore;
int nGender;
};//结构体变量名
int main()
{
int nNum;
//定义结构体变量
STUINFO stcXiaomingInfo;
//使用结构体变量,是通过.来访问结构体中的成员(字段)的
//使用某一个成员的时候,它是什么类型,就按照什么类型来使用
strcpy_s(stcXiaomingInfo.szName, 20, "xiaoming");
stcXiaomingInfo.nAge = 18;
stcXiaomingInfo.dHeight = 175.5;
stcXiaomingInfo.nGender = 1;
stcXiaomingInfo.nScore = 98;
//结构体变量的初始化
STUINFO stcXiaohongInfo = {"xiaohong",20};
STUINFO stcXiaoheiInfo = { "xiaohei",20 };
//给xiaohei 从键盘上输入身高,性别,分数
printf("请输入身高");
scanf_s("%lf", &stcXiaoheiInfo.dHeight);
printf("请输入性别");
scanf_s("%d", &stcXiaoheiInfo.nGender);
printf("请输入分数");
scanf_s("%d", &stcXiaoheiInfo.nScore);
printf("请输入姓名");
scanf_s("%s", &stcXiaoheiInfo.szName,20);
//输出xiaoming和xiaohei的信息
printf("%s %d %lf %d %d", stcXiaomingInfo.szName,
stcXiaomingInfo.nAge, stcXiaomingInfo.dHeight,
stcXiaomingInfo.nGender, stcXiaomingInfo.nScore);
printf("%s %d %lf %d %d", stcXiaoheiInfo.szName,
stcXiaoheiInfo.nAge, stcXiaoheiInfo.dHeight,
stcXiaoheiInfo.nGender, stcXiaoheiInfo.nScore);
return 0;
}
关于结构体嵌套和结构体数组的使用:
struct STUINFO{ //STUINFO是类型名
char szName[20];
int nAge;
double dHeight;
int nScore;
int nGender;
};//结构体变量名
struct POINT
{
int x;
int y;
};
//结构体的嵌套
struct CIRCLE
{
POINT stcCirPoint;
double r;
};
int main()
{
STUINFO stcStuArray[5] = { 0 };
//循环遍历输入学生的信息
for (int i = 0; i < 5; i++)
{
printf("请输入学生的信息:");
scanf_s("%s %d %lf %d %d",
stcStuArray[i].szName, 20,
&stcStuArray[i].nAge, &stcStuArray[i].dHeight,
&stcStuArray[i].nScore, &stcStuArray[i].nGender);
}
//结构体的嵌套
POINT pt = { 10,20 };
CIRCLE yuan;
yuan.stcCirPoint.x = 100;
yuan.stcCirPoint.y = 200;
scanf_s("%d", &yuan.stcCirPoint.x);
return 0;
}
联合体:
联合体的使用语法,和结构体一摸一样的。
区别:
联合体所有的成员共用内存空间。
结构体的每一个成员独占内存空间。
联合体有什么用??节省空间
#define 小学生 1
#define 初中生 1
#define 高中生 1
struct STUINFO {
char szName[20];
int nAge;
int nTpye;
union {
char szParentTel[20];
char szSelfTel[20];
char szId[20];
}SpecialInfo;
};
int main()
{
STUINFO xiaoming = { "xiaoming" };
xiaoming.nAge = 7;
xiaoming.nTpye = 小学生;
scanf_s("%s", xiaoming.SpecialInfo.szParentTel, 20);
return 0;
}
类型的定义:
typedef和结构体的连用属于是一个历史遗留问题
//类型定义
//typedef 能够给一个类型重新名一个名字
typedef int INT;
typedef struct _INFO
{
char szName[20];
int nAge;
int nId;
}INFO;
struct TEST
{
int a;
int b;
};
int main()
{
struct _INFO stc;//C语言的写法
INFO nihao;
TEST obj;
return 0;
}
堆空间:
我们需要一种能够在程序运行的期间,动态的决定,存储数据空间大小的能力。
我们需要借助malloc这个函数。
申请到的地址 malloc (你需要多大内存);
int main()
{
//我想申请能够存储10个整数的空间
//然后遍历输入
//遍历输出
int *p = NULL;
p = (int *)malloc(10 * sizeof(int));
//我们使用指针和数组是非常类似的
//输入
for (int i = 0; i < 10; i++)
{
printf("请输入一个数:");
scanf_s("%d", &p[i]);
}
//输出
for (int i = 0; i < 10; i++)
{
printf("%d ",p[i]);
}
free(p);
p = NULL;
return 0;
}
}
数组和堆有什么区别:
1 数组的长度,是常量, 堆的大小,可以是变量
int main()
{
int n = 0;
int *p = NULL;
printf("你需要存储多少个整数:");
scanf_s("%d", &n);
//int Arr[n];//数组长度必须是常量
p = (int *)malloc(n * sizeof(int));
//将一块内存,设置为一个值
memset(
p,//起始地址
0, //要设置的值
n * sizeof(int)
);
return 0;
}
2 数组由系统自己释放,堆需要由我们自己释放
int main()
{
int n = 0;
int *p = NULL;
printf("你需要存储多少个整数:");
scanf_s("%d", &n);
//int Arr[n];//数组长度必须是常量
while(1)
{
//p = (int *)malloc(n * sizeof(int));
int Arr[1024];
}
return 0;
}
悬空指针和野指针
悬空指针:释放了,但是没有被置为NULL的指针
释放完的指针,应该及时被置为NULL
野指针:没有被初始化的指针,就是野指针。
使用悬空指针或者使用野指针,都会造成程序崩溃。