一个栈的题目

本文探讨了C/C++中栈内存的释放时机,并通过具体的代码示例解析了如何正确使用栈内存及函数返回值。文中详细分析了不同函数调用方式(如_cdecl)对栈内存的影响。

http://stor.chinaunix.net/bbs/archiver/tid-897190.html

题目如下

栈内存何时释放?

char * func1()
{
char a[10];
char *p;

        strcpy(a,"abc");
        p = a;
        return p;
}


main()
{
char *p;

        strcpy(p,func1());
        printf("%s/n",p);
}

打印结果:abc
栈内存是在cp之后释放的吗?
首先程序就有个错误
在main() 中,char* p 只有声明,没有定义
后面却strcpy ,所以编译不通过。
改成char* p=new char[8];
结果p 是指向"abc"的,很多说是偶然,其实偶然中存在这必然,我们先看怎么改变堆栈,是其不指向"abc"呢
void func2()
{
 char x[10];
 for(int i=0;i<10;i++)
 {
  x[i]='o';
 }
}
main这样写
  char *p=new char[10];
  char* d=func1();
  func2();
  strcpy(p,d);
  printf("%s/n",p);
结果改变了,func2()改变了堆栈内容
为什么strcpy没有改变堆栈呢,估计要从汇编上看了,、
strcpy 不是stdcall,而是_cdecl,从后面的add esp,8看出
_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,
我们用od跟下,下面是strcpy的前面的汇编
102AEC50 >  57              push    edi
102AEC51    8B7C24 08       mov     edi, dword ptr [esp+8]
102AEC55    EB 6E           jmp     short 102AECC5
102AEC57    8DA424 00000000 lea     esp, dword ptr [esp]
102AEC5E    8BFF            mov     edi, edi
102AEC60 >  8B4C24 04       mov     ecx, dword ptr [esp+4]
102AEC64    57              push    edi
102AEC65    F7C1 03000000   test    ecx, 3
102AEC6B    74 13           je      short 102AEC80
102AEC6D    8A01            mov     al, byte ptr [ecx]
102AEC6F    83C1 01         add     ecx, 1
102AEC72    84C0            test    al, al
102AEC74    74 3D           je      short 102AECB3
呵呵,inline吗 ? 只有一句push edi 破坏堆栈,根本影响不到前面call 的局部变量
所以总结一下:
返回堆栈数据,后边的call 不必须是strcpy ,memcpy不破坏堆栈的call,否则,后果不难想象!
题目中的语句也可以这样写
char* d=func1();          
strcpy(p,d);
效果是一样的
<think>好的,我现在需要给用户介绍一下的基本题目。首先,我得回想一下的基本概念和常见应用场景,这样才能确定哪些题目属于的典型问题。是一种后进先出(LIFO)的数据结构,常用的操作有入(push)、出(pop)、查看顶元素(peek)等。基于这些特性,常用于处理对称性、递归、括号匹配等问题。 接下来,我应该分门别类地列举常见的题目类型。首先想到的是括号匹配问题,比如有效的括号、最长有效括号子串等。这类题目通常需要检查括号是否正确闭合,能很好地处理这种嵌套结构。 然后是表达式求值问题,比如逆波兰表达式求值、基本计算器等。这类题目需要处理运算符的优先级和括号,可以帮助管理运算顺序。 接下来是在递归问题中的应用,比如二叉树的前中后序遍历的迭代实现。虽然递归本身使用调用,但用显式可以避免递归的开销或者满足特定需求。 还有单调的问题,这类题目通常涉及寻找下一个更大元素、柱状图中的最大矩形等。单调通过维护内元素的单调性来优化时间复杂度。 另外,还有一些其他类型的题目,比如最小、用队列实现等,这些属于的变种或组合应用。 我需要确保每个分类下都有具体的例子,并简要说明解题思路。比如括号匹配问题中,有效的括号可以通过遍历字符串,遇到左括号入,右括号时检查顶是否匹配,最后是否为空来判断有效性。 在表达式求值方面,逆波兰表达式求值相对直接,遇到数字入,遇到运算符则弹出顶两个元素运算后结果入。而基本计算器则需要处理运算符优先级和括号,通常需要两个一个存数字,一个存运算符,或者转换为逆波兰表达式再计算。 单调的例子比如每日温度,寻找数组中每个元素的下一个更高温度的天数,维护一个递减,遇到更高温度时弹出顶元素并计算天数差。 此外,需要提醒用户注意的边界条件,如空时的操作,避免出现空异常。同时,在解决问题时,可以先用例子手动模拟的操作,帮助理清思路。 最后,总结的应用场景和解题技巧,强调练习的重要性,建议用户从简单题开始逐步深入,理解在不同问题中的灵活运用。</think>是一种后进先出(LIFO)的数据结构,常用于处理对称性、递归、括号匹配等问题。以下是的常见题型及解题思路: --- ### 一、括号匹配类问题 **核心思想**:利用记录未匹配的括号,检查闭合顺序是否正确。 1. **有效的括号** - 题目:判断字符串中的括号是否有效闭合(如 `()[]{}`)。 - 解法:遍历字符串,左括号入,右括号时检查顶是否匹配。 - 示例代码逻辑: ```python stack = [] for char in s: if char in "({[": stack.append(char) else: if not stack: return False top = stack.pop() if (top == '(' and char != ')') or ...: return False return not stack ``` 2. **最长有效括号** - 题目:找出字符串中最长的有效括号子串(如 `")()())"` 的最长子串是 `4`)。 - 解法:中记录最后一个未匹配的右括号下标,计算长度差。 --- ### 二、表达式求值类问题 **核心思想**:利用管理运算符优先级和操作数。 1. **逆波兰表达式求值** - 题目:根据逆波兰表示法(如 `["2","1","+","3","*"]`)求值。 - 解法:数字入,遇到运算符则弹出顶两个元素运算,结果入。 2. **基本计算器** - 题目:实现支持加减乘除和括号的表达式求值(如 `"(1+(4+5+2)-3)+(6+8)"`)。 - 解法:使用两个(数字、运算符),处理优先级和括号。 --- ### 三、单调类问题 **核心思想**:维护内元素的单调性(递增或递减),优化时间复杂度。 1. **每日温度** - 题目:找出每日温度后续更高温度的天数差(如 `[73,74,75,71]` → `[1,1,0,0]`)。 - 解法:维护递减,遇到更高温度时弹出顶元素并计算下标差。 2. **柱状图中的最大矩形** - 题目:求柱状图中能勾勒出的最大矩形面积。 - 解法:维护递增,确定每个柱子左右边界。 --- ### 四、与递归的转换 **核心思想**:用显式模拟递归调用1. **二叉树的中序遍历** - 解法:用保存未访问的节点,模拟递归过程。 - 代码逻辑: ```python stack = [] res = [] while stack or root: while root: # 左子树入 stack.append(root) root = root.left root = stack.pop() res.append(root.val) root = root.right ``` --- ### 五、的变种问题 1. **最小** - 题目:设计一个支持 `push`、`pop`、`top` 和 `getMin` 的,且时间复杂度为 $O(1)$。 - 解法:用辅助同步记录最小值。 2. **用队列实现** - 题目:仅用队列的 `push`、`pop` 等操作实现。 - 解法:每次插入新元素时调整队列顺序,使队首始终为顶。 --- ### 练习建议 1. **从简单题入手**:如有效的括号、用实现队列。 2. **逐步深入**:尝试单调和表达式求值类问题。 3. **手动模拟操作**:画图分析元素入过程,帮助理解逻辑。 通过练习以上题型,可以掌握的核心应用场景和解题技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值