计算c语言的栈空间大小

在大工程开发过程中,总有需要知道实现某部分功能的代码的栈空间大小的情况,这里就介绍一下如何获取.
代码的栈空间相关知识这里就不展开描述了,可以去看看其他文章的介绍

环境

这里用的ubuntu, gcc 5.4.0

gcc部分特性

直接用代码来表明其特性,事实上我都是用这种方式来测试得出的结论,并没有找到官方的描述

代码1

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

int func(uint32_t a, uint32_t b)
{
    uint32_t t0;
    uint32_t t1;
    uint32_t t2;
    printf("a[%p] b[%p] t0[%p] t1[%p] t2[%p]\n", &a, &b, &t0, &t1, &t2);
}

int main()
{
    uint32_t v1 = 0;
    uint32_t v2 = 1;
    printf("v1[%p] v2[%p]\n", &v1, &v2);

    func(v1, v2);
    return 0;
}

结果1

v1[0x7ffc43456950] v2[0x7ffc43456954]
a[0x7ffc4345691c] b[0x7ffc43456918] t0[0x7ffc4345692c] t1[0x7ffc43456930] t2[0x7ffc43456934]

栈空间分布(函数相关的栈空间没有示明)
p1

结论1: 同类型的单个变量,先声明会后压栈


代码2

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

int func(uint32_t a, uint32_t b)
{   
    uint32_t t4[10];
    uint32_t t0;
    uint32_t t1;
    uint32_t t2;
    printf("a[%p] b[%p] t0[%p] t1[%p] t2[%p] t4[%p]\n", &a, &b, &t0, &t1, &t2, &t4);
}

int main()
{
    uint32_t v1 = 0;
    uint32_t v2 = 1;
    printf("v1[%p] v2[%p]\n", &v1, &v2);

    func(v1, v2);
    return 0;
}

结果2

v1[0x7ffc43ce99d0] v2[0x7ffc43ce99d4]
a[0x7ffc43ce997c] b[0x7ffc43ce9978] t0[0x7ffc43ce9984] t1[0x7ffc43ce9988] t2[0x7ffc43ce998c] t4[0x7ffc43ce9990]

栈空间分布
p2

结论2:同类型的单个变量,需要的空间越大,越先压栈


代码3

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

int func(uint32_t a, uint32_t b)
{   
    uint32_t t4[10];
    uint32_t t5[5];
    uint8_t  t6[2];
    uint32_t t0;
    uint32_t t1;
    uint32_t t2;
    uint8_t  t3;
    printf("a[%p] b[%p] t0[%p] t1[%p] t2[%p] t3[%p] t4[%p] t5[%p] t6[%p]\n", &a, &b, &t0, &t1, &t2, &t3, &t4, &t5, &t6);
}

int main()
{
    uint32_t v1 = 0;
    uint32_t v2 = 1;
    printf("v1[%p] v2[%p]\n", &v1, &v2);

    func(v1, v2);
    return 0;
}

栈空间分布
p3

结论3: 对于数组和单个变量,总是先压栈数组,再压栈单个变量;对于单个变量,变量长度越大总是越先压栈。

综上,在函数最开头声明的uint8_t类型的单个变量,总是会在该函数中最后压栈(不包括函数变量)

有了上面的结论,就只需要在每个函数开头,声明一个uint8_t类型的变量,并获取该变量的地址,地址值最小的则是用到的最大栈空间,使用示例如下

#include <stdio.h>
#include <stdint.h>

uint32_t minEsp;

int func(uint32_t a, uint32_t b)
{   
    uint8_t  tmpT;
    minEsp = ((uint32_t)(uint64_t)&tmpT < minEsp) ? (uint32_t)(uint64_t)&tmpT : minEsp;

    uint32_t t4[10];
    uint32_t t5[5];
    uint8_t  t6[2];
    uint32_t t0;
    uint32_t t1;
    uint32_t t2;
    uint8_t  t3;
    printf("a[%p] b[%p] t0[%p] t1[%p] t2[%p] t3[%p] t4[%p] t5[%p] t6[%p]\n", &a, &b, &t0, &t1, &t2, &t3, &t4, &t5, &t6);
}

int main()
{
    uint8_t tmpV;
    uint32_t baseEbp = (uint32_t)(uint64_t)(&tmpV);
    minEsp = baseEbp;

    uint32_t v1 = 0;
    uint32_t v2 = 1;
    printf("v1[%p] v2[%p]\n", &v1, &v2);
    
    func(v1, v2);
    printf("stack size: %u\n", (uint32_t)(baseEbp - minEsp));
    return 0;
}

PS:该结论是通过测试代码得出,并没有在标准文档中获取

至于如何识别c函数,在我另一篇博文中有介绍:
python正则表达式匹配c语言的函数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
今年9月份参加计算机二级考试的同学请转载 作者:天使~之戀 已被分享1次 评论(0) 复制链接 分享 转载 删除 下面的138道题目,在二级考试中命中率极高。 一、选择题 (1) 下面叙述正确的是(C) A. 算法的执行效率与数据的存储结构无关 B. 算法的空间复杂度是指算法程序中指令(或语句)的条数 C. 算法的有穷性是指算法必须能在执行有限个步骤之后终止 D. 以上三种描述都不对 (2) 以下数据结构中不属于线性数据结构的是(C) A. 队列 B. 线性表 C. 二叉树 D. (3) 在一棵二叉树上第5层的结点数最多是(B) 注:由公式2k-1得 A. 8 B. 16 C. 32 D. 15 (4) 下面描述中,符合结构化程序设计风格的是(A) A. 使用顺序、选择和重复(循环)三种基本控制结构表示程序的控制逻辑 B. 模块只有一个入口,可以有多个出口 C. 注重提高程序的执行效率 D. 不使用goto语句 (5) 下面概念中,不属于面向对象方法的是 (D) 注:P55-58 A. 对象 B. 继承 C. 类 D. 过程调用 (6) 在结构化方法中,用数据流程图(DFD)作为描述工具的软件开发阶段是(B) A. 可行性分析 B. 需求分析 C. 详细设计 D. 程序编码 (7) 在软件开发中,下面任务不属于设计阶段的是(D) A. 数据结构设计 B. 给出系统模块结构 C. 定义模块算法 D. 定义需求并建立系统模型 (8) 数据库系统的核心是(B) A. 数据模型 B. 数据库管理系统 C. 软件工具 D. 数据库 (9) 下列叙述中正确的是(C) A.数据库是一个独立的系统,不需要操作系统的支持 B.数据库设计是指设计数据库管理系统C.数据库技术的根本目标是要解决数据共享的问题 D.数据库系统中,数据的物理结构必须与逻辑结构一致 (10) 下列模式中,能够给出数据库物理存储结构与物理存取方法的是(A) 注:P108 A. 内模式 B. 外模式 C. 概念模式 D. 逻辑模式 (11) 算法的时间复杂度是指(C) A. 执行算法程序所需要的时间 B. 算法程序的长度 C. 算法执行过程中所需要的基本运算次数 D. 算法程序中的指令条数 (12) 算法的空间复杂度是指(D) A. 算法程序的长度 B. 算法程序中的指令条数 C. 算法程序所占的存储空间 D. 算法执行过程中所需要的存储空间 (13) 设一棵完全二叉树共有699个结点,则在该二叉树中的叶子结点数为(B) 注:利用公式n=n0+n1+n2、n0=n2+1和完全二叉数的特点可求出 A. 349 B. 350 C. 255 D. 351 (14) 结构化程序设计主要强调的是(B) A.程序的规模 B.程序的易读性 C.程序的执行效率 D.程序的可移植性 (15) 在软件生命周期中,能准确地确定软件系统必须做什么和必须具备哪些功能的阶段是(D) 注:即第一个阶段 A. 概要设计 B. 详细设计 C. 可行性分析 D. 需求分析 (16) 数据流图用于抽象描述一个软件的逻辑模型,数据流图由一些特定的图符构成。下列图符名标识的图符不属于数据流图合法图符的是(A) 注:P67 A. 控制流 B. 加工 C. 数据存储 D. 源和潭 (17) 软件需求分析阶段的工作,可以分为四个方面:需求获取、需求分析、编写需求规格说明书以及(B) 注:P66 A. 阶段性报告 B. 需求评审 C. 总结 D. 都不正确 (18) 下述关于数据库系统的叙述中正确的是(A) A. 数据库系统减少了数据冗余 B. 数据库系统避免了一切冗余 C. 数据库系统中数据的一致性是指数据类型的一致 D. 数据库系统比文件系统能管理更多的数据 (19) 关系表中的每一横行称为一个(A) A. 元组 B. 字段 C. 属性 D. 码 (20) 数据库设计包括两个方面的设计内容,它们是(A) A. 概念设计和逻辑设计 B. 模式设计和内模式设计 C. 内模式设计和物理设计 D. 结构特性设计和行为特性设计 (21) 下列叙述中正确的是(A) A. 线性表是线性结构 B. 与队列是非线性结构 C. 线性链表是非线性结构 D. 二叉树是线性结构 (22) 下列关于的叙述中正确的是(D) A. 在中只能插入数据 B. 在中只能删除数据 C. 是先进先出的线性表 D. 是先进后出的线性表 (23) 下列关于队列的叙述中正确的是(C) A. 在队列中只能插入数据 B. 在队列中只能删除数据 C. 队列是先进先出的线性表 D. 队列是先进后出的线性表 (24) 对建立良好的程序设计风格,下面描述正确的是(A) 注:P48 A. 程序应简单、清晰、可读性好 B. 符号名的命名要符合语法 C. 充

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值