2017-05-30 77 views
0

作为一个初学者我已经了解到,唯一的变量定义在C分配内存,但以下程序的输出是0x7ffd12792034我在C中声明了一个变量。编译器如何为变量分配一个内存空间?

#include<stdio.h> 


int main(char args[], int vargs) 
{ 
    int max; 
    printf("%p\n", &max); 
} 
+2

'int max;'是一个变量定义。 – user2357112

+0

@ user2357112那么函数声明是什么呢?我认为声明是只提供名称和类型而不是值的东西,定义是声明+值。我错了吗 ? – smartnerd

+2

int main(char args [],int vargs)' - >'int main(int argc,char * args [])'或'int main(void)' – BLUEPIXY

回答

3

一个local variable很可能坐在call stack(但有时,编译器会optimize只能在一些processor register或甚至完全忘记它)。你的int max;是一个局部变量定义。它的初始值是不确定的,这实际上意味着它保存了之前存储位置(或寄存器)中的所有内容。

您的程序正在打印该调用堆栈上的本地变量的地址。

由于ASLR该地址的实际值可能会改变(或不是)从一个程序执行到下一个。它是具体实现。

顺便说一句,你应该在编译时启用所有的警告和调试信息。如果您使用GCC,则应使用gcc -Wall -Wextra -g进行编译。您至少会有一些警告,特别是因为您的main函数有错误的签名。它应该是int main(int argc, char**argv),并且运行时环境保证argc至少为1,并且argv数组为NULL已终止,其中argc参数不是NULLunaliased字符串。

当心undefined behavior

+0

哦,所以你的意思是在一个函数中总是定义一个局部变量? – smartnerd

+1

当然可以。它可能会或不会被初始化。 –

+1

不,变量的地址是可以坐在某个寄存器中的。它们可能在调用堆栈中有一个插槽。 –

1

您实际上已经在中定义了这是一个变量,未声明。

如果您使用过extern关键字,您将会有一个声明。但是因为你没有,你有一个定义。

初始化程序如int max = 1;不需要定义。该值在未指定之后才会指定,但仍然是一个定义。

如果您在没有初始化程序的情况下在文件范围声明了该变量,那么您将有一个暂定义。之后您可以使用初始化程序进行完整定义,但它必须与试验性定义的类型相匹配。

+0

但我读到C中的所有函数和变量都默认预置了extern吗? – smartnerd

+0

@smartnerd不知道你读了什么,但我想你可能误解了它。 –

+1

@smartnerd默认情况下,函数声明是'extern'。这些很容易区分,因为它们以';'结尾,而函数定义有一个主体。对于一个变量,你应该为一个声明指定'extern'。 – dbush

0

您正在打印内存中占用的地址int max并准备初始化。通过输入int max,如果你给它一个值,你已经有了变量存储的地方。

0

C抽象机器没有定义编译器将在哪里分配原子数据类型的情况。

查看特定实现的唯一方法是反汇编它。 -0x4(%rbp) -

4004d7:  55      push %rbp 
    4004d8:  48 89 e5    mov %rsp,%rbp 
    4004db:  48 83 ec 10    sub $0x10,%rsp 
    4004df:  48 8d 45 fc    lea -0x4(%rbp),%rax 
    4004e3:  48 89 c6    mov %rax,%rsi 
    4004e6:  bf 84 05 40 00   mov $0x400584,%edi 
    4004eb:  b8 00 00 00 00   mov $0x0,%eax 
    4004f0:  e8 fb fe ff ff   callq 4003f0 <[email protected]> 
    4004f5:  b8 00 00 00 00   mov $0x0,%eax 
    4004fa:  c9      leaveq 
    4004fb:  c3      retq 
    4004fc:  0f 1f 40 00    nopl 0x0(%rax) 

在这种情况下,它在栈上的偏移-4-base_pointer分配的空间。

相关问题