C++ 在堆栈上定位局部变量&;使用指针算术
我读到,在函数中,局部变量被放在堆栈上,因为它们是在参数先放在堆栈上之后定义的 也提到了这一点 5.所有函数参数都放在堆栈上。6.说明书 函数内部开始执行。7.局部变量被推送 在定义堆栈时将其添加到堆栈上 所以我认为C++代码是这样的:C++ 在堆栈上定位局部变量&;使用指针算术,c++,memory-management,stack,C++,Memory Management,Stack,我读到,在函数中,局部变量被放在堆栈上,因为它们是在参数先放在堆栈上之后定义的 也提到了这一点 5.所有函数参数都放在堆栈上。6.说明书 函数内部开始执行。7.局部变量被推送 在定义堆栈时将其添加到堆栈上 所以我认为C++代码是这样的: #include "stdafx.h" #include <iostream> int main() { int a = 555; int b = 666; int *p = &a; std::cout
#include "stdafx.h"
#include <iostream>
int main()
{
int a = 555;
int b = 666;
int *p = &a;
std::cout << *(p+1);
return 0;
}
#包括“stdafx.h”
#包括
int main()
{
INTA=555;
int b=666;
int*p=&a;
你的假设在理论上是正确的(从CS的角度)
在实践中,不能保证以这种方式进行指针运算,期望得到这些结果
例如,您的假设“所有函数参数都放在堆栈上”是不正确的:函数参数的分配是由实现定义的(取决于体系结构,它可以使用寄存器或堆栈),并且编译器可以在必要时在寄存器中自由分配局部变量
此外,空值“int
大小为4字节,因此向指针添加4到b
”是错误的。编译器可以在a
和b
之间添加填充,以确保内存对齐
这里的结论是:不要使用低级技巧,它们是实现定义的。即使你必须(不管我们的建议如何)这样做,你也必须知道编译器是如何工作的以及它是如何生成代码的。你的假设在理论上是正确的(从CS的角度来看)
在实践中,不能保证以这种方式进行指针运算,期望得到这些结果
例如,您的假设“所有函数参数都放在堆栈上”是不正确的:函数参数的分配是由实现定义的(取决于体系结构,它可以使用寄存器或堆栈),并且编译器可以在必要时在寄存器中自由分配局部变量
此外,空值“int
大小为4字节,因此向指针添加4到b
”是错误的。编译器可以在a
和b
之间添加填充,以确保内存对齐
这里的结论是:不要使用低级技巧,它们是实现定义的。即使你必须(不管我们的建议如何)这样做,你也必须知道编译器是如何工作的以及它是如何生成代码的。其他人都说了什么(即“不要这样做”)绝对正确。不要这样做。但是,为了真正回答您的问题,p+1
很可能指向调用者堆栈帧的指针或返回地址本身。当您在堆栈指针上推送某个内容时,系统维护的堆栈指针将递减。从官方角度讲,这取决于实现,但每个我见过的堆栈指针(从16位时代开始)是这样的。因此,如果如您所说,局部变量在初始化时被推送到堆栈上,&a
应该=&b+1
也许有一个例子可以说明。假设我在没有优化的情况下编译32位x86的代码,并且在调用函数之前堆栈指针esp
为20(这是不可能的,记录在案)。这就是调用cout
的行前面的内存:
4: 12 (value of p)
8: 666 (value of b)
12: 555 (value of a)
16: -858993460 (return address)
p+1
,因为p
是一个int*
,所以为16。此位置的内存不受读取保护,因为需要返回调用函数
请注意,这个答案是学术性的;可能是编译器的优化或处理器之间的差异导致了意外的结果。但是,我不希望在任何具有我见过的任何调用约定的处理器体系结构上p+1
到=&b
,因为堆栈通常向下增长。还有一个人说过(即“不要那样做”)绝对正确。不要这样做。但是,为了真正回答您的问题,p+1
很可能指向调用者堆栈帧的指针或返回地址本身。当您在堆栈指针上推送某个内容时,系统维护的堆栈指针将递减。从官方角度讲,这取决于实现,但每个我见过的堆栈指针(从16位时代开始)是这样的。因此,如果如您所说,局部变量在初始化时被推送到堆栈上,&a
应该=&b+1
也许有一个例子可以说明。假设我在没有优化的情况下编译32位x86的代码,并且在调用函数之前堆栈指针esp
为20(这是不可能的,记录在案)。这就是调用cout
的行前面的内存:
4: 12 (value of p)
8: 666 (value of b)
12: 555 (value of a)
16: -858993460 (return address)
p+1
,因为p
是一个int*
,所以为16。此位置的内存不受读取保护,因为需要返回调用函数
请注意,这个答案是学术性的;可能是编译器的优化或处理器之间的差异导致了意外的结果。但是,在任何具有我见过的任何调用约定的处理器体系结构上,我不希望p+1
到=&b
,因为堆栈通常向下增长。p+1 >是。<代码> *(p+1)< /C>是未定义的行为。不是必须做任何事情,而是改变<代码> p>代码>指向<代码> b>代码>。没有优化,<代码> *(& b+1)< /C> >在运行时,在Celru上打印1。而且,由于C++语言/标准没有任何“栈”的概念,所以句子。“所有函数参数都放在堆栈上”基本上是BS。如果你想知道的话,也有编译器优化(你可能想让你的变量变为volatile
并搜索一个重复的…)