c++ - c语言中的内存分配
PHPz
PHPz 2017-04-17 11:04:28
0
4
571

这个问题是关于c和c++中对于参数,变量在内存中地址分配的问题。对于以下代码

int main (int argc, char *argv[]) {
  int a;
  int b;
  a = 1;
  b = 2;
  return 0;
}

我的理解是,main函数是通过初始函数调用,main函数实际和其他函数一样。
在初始函数调用main函数后,会先将返回地址压入堆栈,接着将参数压入堆栈。面对函数中定义的局部变量,将会按照定义顺序分配堆栈内存空间。而堆栈是从高地址向低地址生长的,所以我认为&a > &b。
然而,在gdb调试过程中,我发现&b > &a。请问我的理解在哪里错了?

PHPz
PHPz

学习是最好的投资!

全員に返信(4)
大家讲道理

局部变量的空间不是一个一个压入栈中的,而是一次性分配好的,所以理解为变量依次入栈是错误的。C语言也没有规定局部变量在内存中的位置,只是常常实现为先定义的变量在高地址、后定义的变量在低地址。不过局部变量在栈上的位置没有绝对的关系,甚至不一定会出现在栈上。比如你的代码做这样的调整,改成下面这样:

#include<stdio.h>

int main()
{
  int a = 1;
  int b = 2;

  printf( "a = %d, b = %d\n", a, b );
  printf( "&a = %08x, &b = %08x\n", &a, &b );
  return 0;
}

这个时候你会发现a变量确实分配在高地址,而b变量分配在低地址。如果你把你的程序加上-O2参数优化一下,那么a和b这两个变量因为没有被真正的使用,而被编译器优化掉,你直接p &a会得不到任何的值。

いいねを押す +0
刘奇

“栈”这个数据结构本身并没有规定其生长的方向,具体实现中向高地址或者低地址生长都无妨。但是对于操作系统而言,栈的生长方向一般是取决于处理器对PUSH/POP操作的实现。对于x86来说,PUSH以后SP/ESP的值是减小,因此它是向低地址生长的,样例代码:

#include <stdio.h>

void stack_growth(char *function_parameter) {
    char local;
    if (&local > function_parameter)
        printf("up\n");
    else
        printf("down\n");
    printf("%p %p\n", &local, function_parameter);
}

int main()
{
    char c = 'c';
    stack_growth(&c);
    return 0;
}

而声明一个变量,无非是告诉编译器,在栈上给它准备一块空间。因此你所提及的情况,实际上与栈无直接关系:a先声明的话,就一定会在栈上为它分配空间吗?举个最简单的栗子,如果a根本没被用到,编译器完全可以不为它分配空间。所以这个最终还是取决于编译器的实现。

补充一段WIKI吧:

Some processors families, such as the x86, have special instructions for manipulating the stack of the currently executing thread. Other processor families, including PowerPC and MIPS, do not have explicit stack support, but instead rely on convention and delegate stack management to the operating system's Application Binary Interface (ABI).
いいねを押す +0
Peter_Zhu

系统分配的内存区叫“栈区”,手动分配的内存空间叫“堆区”。
在“栈区”地址扩展方向是从高地址向低地址,“堆区”相反。

いいねを押す +0
阿神

lz 你帖下编译命令?

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート