目录
函数栈帧的创建和销毁::
解决问题:
1.局部变量是怎么创建的?
2.为什么局部变量的值是随机值?
3.函数是怎么传参的?
4.形参和实参是什么关系?
5.函数调用结束后怎么返回的?
C语言编程训练
1.编写程序将三个整数从大到小输出
2.编写程序打印1—100之间所有3的倍数的数字
3.编写程序求两个数的最大公约数
4.编写程序计算1/1-1/2+1/3-1/4+1/5+......+1/99-1/100
5.求十个整数中最大值
6.打印九九乘法口诀表
7.实现一个函数来打印乘法口诀表,行数列数自己指定
知识铺垫:
为了观察函数栈帧的创建和销毁,我们这里采用最简单的代码,并将其做了详细的拆分。
#include
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
printf("%d\n", c);
return 0;
}
有关寄存器的知识铺垫:
寄存器有很多像eax,ebx,ecx,edx,那么聊函数栈帧就要搞懂ebp,esp这两个寄存器,ebp,esp存放的是地址,这两个寄存器是用来维护函数栈帧的。
我们知道每调用一个函数,都要在栈区上为它分配空间。
对于上面的一段代码——
Add函数的汇编代码:
函数栈帧建立的详细过程:
答:首先为此次函数调用创建函数栈帧,在函数栈帧找空间存放局部变量值。
随机值是系统开辟完函数栈帧后系统随机放进去的。
形参在刚开始调用之前就已经传过去了,形式参数从左向右传递。
形参是实参的临时拷贝,值相同但空间不同,因此改变形参的值不会影响实参的值。
返回值并不会随着函数作用域的销毁而销毁,而是放在eax中准备返回,当通过pop出栈回到main函数中再将返回值放到局部变量中。
#include
//代码1
int main()
{
int a = 0;
int b = 0;
int c = 0;
int temp = 0;
scanf("%d %d %d", &a, &b, &c);
if (a < b)
{
temp = a;
a= b;
b = temp;
}
if (a < c)
{
temp = a;
a = c;
c = temp;
}
if (b < c)
{
temp = b;
b = c;
c = temp;
}
printf("%d %d %d\n", a, b, c);
return 0;
}
//代码2:函数版
Swap(int* px, int* py)
{
int temp = *px;
*px = *py;
*py = temp;
}
int main()
{
int a = 0;
int b = 0;
int c = 0;
scanf("%d %d %d", &a, &b, &c);
if (a < b)
{
Swap(&a, &b);
}
if (a < c)
{
Swap(&a, &c);
}
if (b < c)
{
Swap(&b, &c);
}
printf("%d %d %d\n", a, b, c);
return 0;
}
#include
//打印1-100之间所有3的倍数的数字
//代码1
int main()
{
int i = 0;
for (i = 1; i <= 100; i++)
{
if (i % 3 == 0)
printf("%d ", i);
}
return 0;
}
//代码2
int main()
{
int i = 0;
for (i = 3; i <= 100; i += 3)
{
printf("%d ", i);
}
return 0;
}
#include
//求两个数的最大公约数
//代码1
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int min = (a < b ? a : b);
int m = min;
while (1)
{
if (a % m == 0 & b % m == 0)
{
break;
}
m--;
}
printf("%d\n", m);
return 0;
}
//代码2
//辗转相除法:24 % 18 == 6 18 % 6 == 0
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
while (a % b)
{
int c = a % b;
a = b;
b = c;
}
printf("%d\n", b);
return 0;
}
//优化
int main()
{
int a = 0;
int b = 0;
int c = 0;
scanf("%d %d", &a, &b);
while (c = a % b)
{
a = b;
b = c;
}
return 0;
}
#include
int main()
{
int i = 0;
double sum = 0.0;
int flag = 1;
for (i = 1; i <= 100; i++)
{
sum = sum + flag*(1.0 / i);//一定不能写成1/i
flag = -flag;//不能写成flag=-1
}
printf("%lf\n", sum);
return 0;
}
#include
//代码1
int main()
{
//准备10个整数
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//找出最大值
int i = 0;
int max = arr[0];//max不能赋值成0来比较负数
for (i = 1; i < 10; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
printf("%d\n",max);
return 0;
}
//代码2
int main()
{
int arr[10] = {0};
//输入数字
int n = 0;
for(n = 0;n < 10;n++)
{
scanf("%d",&arr[n]);
}
//找出最大值
int i = 0;
int max = arr[0];//max不能赋值成0来比较负数
for (i = 1; i < 10; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
printf("%d\n",max);
return 0;
}
#include
int main()
{
int i = 1;
for (i = 1; i <= 9; i++)
{
int j = 0;
for (j = 1; j <= i; j++)
{
printf("%d*%d=%d\t", j, i, i * j);
}
printf("\n");
}
return 0;
}
#include
int main()
{
int i = 0;
int count = 0;//计数
for (i = 1; i <= 100; i++)
{
if (i % 10 == 9)//判断个位是不是9
count++;
if (i / 10 == 9)//判断十位是不是9
count++;
}
printf("count=%d\n", count);
return 0;
}
#include
void print_table(int n)
{
int i = 0;
for (i = 1; i <= n; i++)
{
int j = 0;
for (j = 1; j <= i; j++)
{
printf("%d*%d=%-2d ", j, i, i * j);
}
printf("\n");
}
}
int main()
{
int n = 0;
scanf("%d", &n);
print_table(n);
return 0;
}