一.结构体
定义:
一些值的集合,这些值称为成员变量,结构体的每个成员可以是不同类型的变量
1.结构体(结构)的声明
struct Book(结构体名称)
{
Member-list(成员列表)
}variable-list(变量列表);
1.1结构体的作用:
之前笔记中的类型都是内置型:
char short int ……
所以就有结构体来描述复杂对象
结构体可以是任何类型
1.2结构体变量的创建
1.2.1
struct (结构体名称) (变量名)
struct Stu s1;
1.2.2
在1中的变量列表处直接创建变量s1、s2……
注意:此处的变量是全局变量
struct Stu
{
Member-list
} s1, s2;
1.2.3
使用typedef,就能简写struct成自定义的类型名,如Stu
typedef struct Stu
{
//Member - list
}Stu;//Stu 是重命名产生的新的类型
int main()
{
Stu s1,s2;
return 0;
}
1.3结构体变量的初始化
使用{}进行赋值,有两种方式,如:
struct B
{
char c;
int i;
};
struct S
{
char c;
int num;
int arr[10];
double* pd;
struct B sb;
struct B* pb;
}s1;//s1是全局变量
struct S s2;//s2是全局变量
int main()
{
double d = 3.14;
//按照顺序初始化
struct S s3 = { 'q', 100, {1,2,3}, &d, {'a', 99}, NULL };
//指定成员来初始化
struct S s4 = { .num = 1000, .arr = {1,2,3,4,5} };
return 0;
}
2.结构体成员的访问
分为两种
结构体变量.成员名
结构体指针->成员名
3.结构体变量的传参
推荐传址调用:
a 传址调用能实现的作用比传值调用更大。
b 节省占用栈区空间的大小,行能更高。
二实用调试技巧
1.bug
指飞蛾
事件链接:
点击此处跳转
有兴趣的可以了解一下
由此,飞蛾(bug)就引申为计算机程序的错误
2.调试
2.1定义
寻找错误并解决的过程就是调试
2.2步骤
2.3debug和release
debug:
debug(调试)版本:
不进行优化,由于进行调试
release:
release(发布)版本:
自动进行优化,不能调试,给用户使用的版本
3.windows环境调试介绍
3.1环境准备
debug版本
3.2快捷方式
下面介绍五个最常用的快捷键。
提示:部分机器需要加上Fn键。
补充:
F11更细致:能进入函数内部,并逐条执行其中的语句。
F9创建断点
F5跳过断点前的代码,便于调试
F5还可以使用条件断点,更快捷
如图:
提示:
当循环中存在断点时,F5只会跳到下一次循环中的断点
3.3调试过程中查看当前代码的信息
提示:
1.
推荐使用监视,自己确定要监视的对象,不建议用自动窗口。
2.
部分VS2022在运行前点窗口是看不到上图中的选项的,此时可以先开始调试,再点击窗口,就能看到那些选项了。
调用堆栈:
反映的是函数的调用逻辑,即运行过程
从这里可以看出,函数的运行逻辑:从下往上逐层调用。
概念介绍:
在存储数据时,分为两种,栈和队列
栈:一种数据结构,后进先出,后进的元素在栈区的上面,结束时就先出
队列:先进先出
4.实例
下面向大家介绍两段代码,以便于大家更好的理解调试的重要以及用处。
A
先用一个简单的题目吧:
求1~n的阶乘之和
int main()
{
int i = 0;
int n = 0;
int ret = 1;
int sum = 0;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
int j = 0;
for (j = 1; j <= i; j++)
{
ret *= j;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
我们运行之后会发现结果错误,
这时候我们进行调试,会发现:
ret的值不是我们预期的,
这时我们逐步查找后发现每次循环ret的值都在随之增大,所以应在循环内部加上
ret = 1;
B
观察下面这个程序,并用调试解释其错误的原因。
注意:
这段代码是在VS 上,X86,debug模式下运行的,在解释完这段代码后,会单独进行说明。
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i <=12; i++)
{
arr[i] = 0;
printf("hehe\n");
}
return 0;
}
运行结果:
死循环的打印“hehe”
常识介绍:
数组,随着下标的增长,地址是由低向高变化的,即向下扩展
解释:
在此环境下,数组arr是存储在i地址向上8个字节的地址,所以当其越界至i=12时,arr[12]其地址与i相同,所以改变arr[12]就会改变i,即i也变为0,所以就陷入了死循环。
图解:
编译器的说明
这个代码在VC 6.0下,arr和i之间没有空隙
在gcc下二者之间有一个空隙
提示:
当在release下运行程序时,程序不会报错,因为它自动进行优化,即把i存储在比数组小的地址中,使数组越界也不会访问到i
结语
今天的知识点就介绍到这里,我们下次见。