我有以下主程序创建一个Stack对象,用双打填充它然后弹出它们.代码文件很好,但该pop_back()部分似乎不起作用,而s.back()确实返回正确的值.这怎么可能?
#include "Stack.h"
#include <iostream>
#include <deque>
using namespace std;
int main() {
Stack<double> s(0,0.0);
// Write doubles into Stack
int i ;
for (i=0 ; i<15 ; i++) {
s.push(i*i) ;
}
// Read doubles back from fifo
while (!s.empty()) {
double val = s.pop() ;
std::cout << "Popping value " << val << " from stack" << std::endl ;
}
return 0 ;
}
Run Code Online (Sandbox Code Playgroud)
我的头文件看起来像这样,我省略了与问题无关的部分.
#ifndef STACK_H
#define STACK_H
#include <iostream>
#include …Run Code Online (Sandbox Code Playgroud) 据我了解,在C和C ++中,我们创建在堆栈上大小在编译时已知的数据结构,并使用堆(malloc-free / new-delete)处理大小在编译时未知的数据,是在运行时决定的。为什么,我的g ++编译器允许我执行类似以下代码段的操作。
int main(void)
{
int n ;
cin >> n ; // get the size of array.
int arr[n] ; // create a variable sized array.
.... do other stuff ...
}
Run Code Online (Sandbox Code Playgroud)
具体来说,在数组的情况下:
数组在堆栈上分配了一个连续的内存块,并且在堆栈上上下都有变量,因此必须知道数组的大小,以便堆栈上数组上方的变量,数组本身以及堆栈上数组下方的变量都可以整齐地放入内存。那么如何在堆栈上实现可变大小的数组呢? 为什么甚至有必要?为什么我们不能仅将堆用于可变大小的缓冲区?
编辑:
我从评论中了解到,关于VLA是否为标准,C和C ++有不同的规则,而且尼尔·巴特沃思(Neil Butterworth)的评论指出,同时询问两种语言通常不是一个好主意。谢谢大家,因此我打算从问题中删除C标签,因为我打算主要询问C ++,这从代码片段语法可以明显看出。抱歉造成您的困惑,也感谢您的答复。
假设我们创建了一个用户函数void func().func的堆栈帧是在函数调用时分配的,只要在main等其他函数中调用它.
和printf一样吗?是否 printf的也消耗堆栈帧?
我需要访问main函数中定义的变量a的值,而不将其作为参数传递.
main()
{
int a=10;
func();
printf("%d\n",a);
}
void func(){
//i need access of variable a here.
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
我目前正在学习x86程序集.但是当我使用堆栈进行函数调用时,我仍然不清楚某些事情.我知道调用指令将涉及在堆栈上推送返回地址,然后加载程序计数器和要调用的函数的地址.ret指令将该地址加载回程序计数器.
我的困惑是,在过程/函数中调用ret指令时是否重要?它是否总能找到存储在堆栈中的正确返回地址,或者堆栈指针当前是否必须指向存储返回地址的位置?如果是这种情况,我们不能只使用push和pop而不是call和ret吗?
例如,下面的代码可能是进入函数的第一个代码,如果我们在堆栈上推送不同的寄存器,则必须在以相反的顺序弹出寄存器之后才调用ret指令,以便在pop%ebp指令之后,堆栈指针将指向返回地址所在的堆栈上的正确位置,或者无论它在何处被调用,它仍会找到它?提前致谢
push %ebp
mov %ebp, %esp
//push other registers
...
//pop other registers
mov %esp, %ebp
(could ret instruction go here for example and still pop the correct return address?)
pop %ebp
ret
Run Code Online (Sandbox Code Playgroud) 在c(和c ++)中,可以通过以下方式创建整数数组:
int a[const];
Run Code Online (Sandbox Code Playgroud)
const是编译时常量,或者
int *a = (int *) malloc(...);
Run Code Online (Sandbox Code Playgroud)
根据我的理解,第一个在堆栈上分配内存,第二个在堆上分配内存.现在,据我所知,堆栈上的内存是按顺序排列的,程序可以根据需要从顶部弹出.这意味着阵列中的元素不一定按顺序存储,这听起来很奇怪.
究竟是什么发生在这里?
编辑:
谢谢回复人员.随着你的回答和一些跟进谷歌搜索我找到了我的困惑的来源.我假设程序只会真正使用堆栈的顶部变量,并逐个打开/关闭它们.
如何修改汇编中的堆栈内存块?
我想到了一种方法,那就是:
POP EAX
ADD EAX, 5
PUSH EAX
Run Code Online (Sandbox Code Playgroud)
是否有更短的更有效的方法来做到这一点?
为什么我们可以使用堆栈满足我们的所有需求?
注意:如果您在解释时给出一个例子,那将是非常好的,因为通过示例更容易理解.
抱歉英语不好.
我需要有关Assembly中代码的帮助.
我正在接受这个问题,我的小组只是做了这个汇编代码,它应该和我在#c中所做的一样.
有人可以帮我理解至少在第一步中使用堆栈会发生什么,所以我可以继续并完成剩下的工作吗?
我是Assembly中的一个初学者,但我知道这些行只保存调用函数的值,为被调用函数设置一个框架并为局部变量节省空间,但我无法弄清楚接下来的第一步.
mov ebp
mov ebp,esp
sub esp, 16
Run Code Online (Sandbox Code Playgroud)
这是我在#c中所做的:
void mult_integer(int X[A_Linhas][A_Colunas], int number)
{
int c, l;
for (l = 0; l < A_Linhas; l++)
{
for (c = 0; c < A_Colunas; c++)
{
X[l][c] = number * X[l][c];
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是Assembly中的代码:
mul_integer:
push ebp
mov ebp, esp
sub esp, 16
mov dword [ebp-4H], 0
jmp L_020
L_017: mov dword [ebp-8H], 0
jmp L_019
L_018: mov edx, dword [ebp-4H]
mov eax, edx
add eax, …Run Code Online (Sandbox Code Playgroud) 我已经拆解了一个使用C 函数的x86 elf二进制文件scanf.
以下是与以下内容相关的反汇编代码块scanf:
0x0804857a 89442404 mov dword [esp + 0x4], eax
0x0804857e c70424b28604. mov dword [esp], 0x80486b2
0x08048585 e8eafdffff call sym.imp.scanf
Run Code Online (Sandbox Code Playgroud)
检查时gdb,地址处的内存0x80486b2包含数据0x7325(ASCII代码中的" %s "字符串).
所以这段代码显然是在堆栈上以相反的顺序推送参数,以便用这两个参数调用.
这通常用C编码
scanfscanfscanf ("%s", &somevar);
在给定汇编代码的情况下,我所期望的是,常量的32位表示形式 0x80486b2被加载到堆栈指针所指向的地址中 ......
但是,该mov指令已经加载了32位表示的任何处于地址 0x80486b2 到堆栈指针指向的地址 ......是吗?
所以我们基本上得到的mov只是将数据从内存位置转移到另一个内存位置,根据这个x86程序集介绍(在众多其他来源中)是非法的(重点是我的):
在需要存储器传输的情况下,必须首先将源存储器内容加载到寄存器中 …