龙空技术网

C语言进阶03-栈内存习题

吃个反物质炮压压惊 243

前言:

现时大家对“c语言数组的习题”大概比较重视,朋友们都需要学习一些“c语言数组的习题”的相关知识。那么小编在网摘上搜集了一些有关“c语言数组的习题””的相关知识,希望兄弟们能喜欢,兄弟们快快来了解一下吧!

01

绘制调用栈

int f1(int k, int m){  int y;  y = k + m;  return y;}void f2(void){  int a = 83;  int c = -74;  c = f1(a, c);  //其他代码}

绘制调用栈:

1、在f1被调用之前.

2、当程序完成了第4行.

3、当程序完成了f1, 且最顶部的栈帧出栈.

解答:

1、在f1被调用之前. f2中初始化a, c后调用的, 所以如下:

栈帧

标志符

地址

f2

c

101

-74

a

100(假定100开始)

83

2、当程序完成了第4行. f1是嵌套在f2中的, 如下:

栈帧

标志符

地址

f1

y

106

9

m

105

-74

k

104

83

值地址

103

101

返回位置

102

13行

f2

c

101

-74

a

100

83

3、当程序完成了f1, 且最顶部的栈帧出栈. 其实就是上面的程序执行完.

栈帧

标志符

地址

f2

c

101

9

a

100

83

02

绘制调用栈2

void f1(int k, int m){  int y;  y = k;  k = m;  m = y;}void f2(void){  int a = 83;  int c = -74;  f1(a, c);  //一些代码}

绘制调用栈

1、当程序已经输入f1并完成了第4行. k和m的值是多少?

2、当程序完成了第6行, 且在f1的栈帧出栈之前. k和m的值是多少呢?

3、当程序完成了f1且f1的栈帧已经出栈时, a和c的值是多少呢?

解答:

1、当程序已经输入f1并完成了第4行. k和m的值是多少?

栈帧

标志符

地址

f1

y

105

83

m

104

-74

k

103

83

返回位置

102

第14行

f2

c

101

-74

a

100

83

2、当程序完成了第6行, 且在f1的栈帧出栈之前. k和m的值是多少呢?

栈帧

标志符

地址

f1

y

105

83

m

104

83

k

103

-74

返回位置

102

第14行

f2

c

101

-74

a

100

83

3、当程序完成了f1且f1的栈帧已经出栈时, a和c的值是多少呢?

a, c值是不变的.

栈帧

标志符

地址

f2

c

101

-74

a

100

83

03

三个问题

1、开发人员怎么才能控制一个变量的地址呢?

答曰: 无法控制.

2、如果相同的程序运行多次, 相同变量的地址会是相同的吗?

答曰: 可能是不同的.

3、一个数组元素的地址是连续的还是离散的?

答曰: 连续的.

04

在DDD(命令行调试程序)上检测调用栈

在linux中输入如下代码命名为p1.c:

#include <stdio.h>#include <stdlib.h>int g1(int a, int b){    int c = (a + b) * b;    printf("g1:   a = %d, b = %d, c = %d\n", a, b, c);    return c;}int g2(int a, int b){    int c = g1(a + 3, b - 11);    printf("g2:   a = %d, b = %d, c = %d\n", a, b, c);    return c - b;}int main(int argc, char **argv){    int a = 5;    int b = 17;    int c = g2(a - 1, b * 2);    printf("main: a = %d, b = %d, c = %d\n", a, b, c);    return EXIT_SUCCESS;}# 使用命令:gcc -g -Wall -Wshadow p1.c -o p1进行编译

-g 表示启用调试, -Wall和-Wshadow启用警告信息. -o表示编译完后的输出文件. 运行结果如下:

# ./p1g1:   a = 7, b = 23, c = 690g2:   a = 4, b = 34, c = 690main: a = 5, b = 17, c = 656

在命令行中输入 gdb p1进入调试模式

gdb p1GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7Copyright (C) 2013 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <;This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-redhat-linux-gnu".For bug reporting instructions, please see:<;...Reading symbols from /data/Clang/p1...done.(gdb)

在g1和g2两个函数处设置断点:

(gdb) b g1Breakpoint 1 at 0x40052b: file p1.c, line 6.(gdb) b g2Breakpoint 2 at 0x400567: file p1.c, line 13.(gdb)

b g1表示在g1开始时设置断点, 当程序到达g1的第一行, 程序将停止. b g2同理.

运行run可以执行.

(gdb) runStarting program: /data/Clang/p1 Breakpoint 2, g2 (a=4, b=34) at p1.c:1313          int c = g1(a + 3, b - 11);Missing separate debuginfos, use: debuginfo-install glibc-2.17-292.el7.x86_64

在g2的断点处停止了. 设置多个断点, 程序将按照被执行的顺序停止在断点处. 不是按照它们被设置的顺序. 继续运行

(gdb) continueContinuing.Breakpoint 1, g1 (a=7, b=23) at p1.c:66           int c = (a + b) * b;

这回在g1的断点处了, 执行"栈回溯”命令:

(gdb) bt#0  g1 (a=7, b=23) at p1.c:6#1  0x000000000040057c in g2 (a=4, b=34) at p1.c:13#2  0x00000000004005d7 in main (argc=1, argv=0x7fffffffe618) at p1.c:22

每一行的起始显示了调用栈的栈帧(0, 1, 2), 与函数g1, g2和main函数相对应. 使用f命令可以看到不同的栈帧:

(gdb) f#0  g1 (a=7, b=23) at p1.c:66           int c = (a + b) * b;

还有一些其他命令, 可以自己摸索, 这里就不阐述了.

标签: #c语言数组的习题