作为一个初学者我已经了解到,唯一的变量定义在C分配内存,但以下程序的输出是0x7ffd12792034我在C中声明了一个变量。编译器如何为变量分配一个内存空间?
#include<stdio.h>
int main(char args[], int vargs)
{
int max;
printf("%p\n", &max);
}
作为一个初学者我已经了解到,唯一的变量定义在C分配内存,但以下程序的输出是0x7ffd12792034我在C中声明了一个变量。编译器如何为变量分配一个内存空间?
#include<stdio.h>
int main(char args[], int vargs)
{
int max;
printf("%p\n", &max);
}
一个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
参数不是NULL
unaliased字符串。
哦,所以你的意思是在一个函数中总是定义一个局部变量? – smartnerd
当然可以。它可能会或不会被初始化。 –
不,变量的地址是可以坐在某个寄存器中的。它们可能在调用堆栈中有一个插槽。 –
您实际上已经在中定义了这是一个变量,未声明。
如果您使用过extern
关键字,您将会有一个声明。但是因为你没有,你有一个定义。
初始化程序如int max = 1;
不需要定义。该值在未指定之后才会指定,但仍然是一个定义。
如果您在没有初始化程序的情况下在文件范围声明了该变量,那么您将有一个暂定义。之后您可以使用初始化程序进行完整定义,但它必须与试验性定义的类型相匹配。
您正在打印内存中占用的地址int max
并准备初始化。通过输入int max
,如果你给它一个值,你已经有了变量存储的地方。
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
分配的空间。
'int max;'是一个变量定义。 – user2357112
@ user2357112那么函数声明是什么呢?我认为声明是只提供名称和类型而不是值的东西,定义是声明+值。我错了吗 ? – smartnerd
int main(char args [],int vargs)' - >'int main(int argc,char * args [])'或'int main(void)' – BLUEPIXY