C 函数,用于在每次调用时创建具有新内存地址的变量
假设有一个函数f,它的主体中包含一个新变量b的声明。 我注意到,每次调用f时,变量b(应该在每次创建和销毁时创建和销毁)(EDIT:不在动态情况下,正如所指出的那样)总是具有相同的内存地址 以下非常简单的代码向您展示了一个示例:C 函数,用于在每次调用时创建具有新内存地址的变量,c,C,假设有一个函数f,它的主体中包含一个新变量b的声明。 我注意到,每次调用f时,变量b(应该在每次创建和销毁时创建和销毁)(EDIT:不在动态情况下,正如所指出的那样)总是具有相同的内存地址 以下非常简单的代码向您展示了一个示例: #include <stdio.h> #include <stdlib.h> void f ( void ){ int b; printf ("%p\n", &b); } int main (){ int i =
#include <stdio.h>
#include <stdlib.h>
void f ( void ){
int b;
printf ("%p\n", &b);
}
int main (){
int i = 0;
while (++i <= 10)
f();
return 0;
}
#包括
#包括
无效f(无效){
int b;
printf(“%p\n”、&b);
}
int main(){
int i=0;
而(++i自动变量的地址取决于函数项上堆栈指针的值,它将是一个固定的偏移量。如果在这样的循环中调用函数:
while (...) {
...
f(...);
...
}
#include <stdio.h>
#include <stdlib.h>
void f (void){
int *b = malloc (sizeof(int));
printf ("%p\n", b);
}
int main (){
int i = 0;
while (++i <= 10)
f();
return 0;
}
编译器生成代码的方式很可能是f
的自动变量始终具有相同的地址。这是您无法轻易更改的
如果我们不使用自动变量,我们可以很容易地得到想要的结果。每次只需在f
中分配一个新变量。当然,这会泄漏大量内存,但没有更好的方法,因为f
必须记住已用于b
的地址,如果您希望b
驻留在不同的位置每次使用的地址和以前使用的地址都不可用(因此被浪费)。也许您正在寻找的是动态内存分配?您可能需要阅读malloc
、calloc
、realloc
和free
的文档(原型为
)
从技术上讲,每个对象都有一个相关的存储类。对于像f
这样的自动变量,这是自动的,通常在堆栈上分配(但也有无堆栈的机器)。对于动态分配的对象,存储类是动态的,通常从堆中分配(但也有无堆机器)
本质上,您不应该依赖具有特定模式或值的地址。您观察到的行为是创建和回收堆栈帧的结果。当在while循环中重复调用f()
时,会发生四种情况:
内存管理单元在堆栈上为其获取一块内存,以保存其参数、局部变量和返回值
局部变量b
在此堆栈帧中声明,由于未初始化,它包含“垃圾数据”(本例中为0xDEADBEEF
)
f()
返回,通过移动“堆栈顶部”指针将其堆栈帧循环上移到main()
堆栈帧。请注意,f()
的堆栈帧的内容永远不会被清除或归零。
函数f()
会立即被再次调用,因此会提取一个内存块。这与第一次调用f()
时提取的内存块完全相同(继续并通过打印b
的地址进行检查)。由于b
未初始化,因此它包含“垃圾数据”,但它是相同的“垃圾数据”(0xDEADBEEF
)在f()
的第一次调用中,此后该位置尚未写入
但是,使用malloc
在堆上分配存储可能无法解决此问题!调用malloc()
,然后调用free()
,然后再调用malloc()
将再次为您提供堆上相同的地址,如此测试程序所示:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
char *ptr1 = malloc(sizeof(char));
printf("Allocated memory at %p\n", ptr1);
free(ptr1);
printf("Freed memory at %p\n", ptr1);
char *ptr2 = malloc(sizeof(char));
printf("Allocated memory at %p\n", ptr2);
free(ptr2);
printf("Freed memory at %p\n", ptr2);
if (ptr1 == ptr2) {
printf("Pointers were the same!\n");
}
return 0;
}
非常接近您所拥有的,但由于b
是一个地址,您可以只打印b
,而不是&b
编辑:图像贷记到我可以问一下你为什么需要它吗?将&b
(类型为int*
)传递到%p
格式(调用void*
)是未定义的行为。在你的问题中,我看不到任何与程序输出类似的东西,而且f
需要修改什么?@MikeCAT从技术上讲是,但这是o这是我不同意该标准的少数几种情况之一。这在所有指针具有相同表示形式的平台(即,您将看到的几乎所有平台)上都有效,而且将来也会有效。您的编辑就快到了,只需在printf中省去&b
。我真的很感谢完整的详细解释-它帮了我很多。最后的“&”…谢谢,我打赌我会花几个小时。祝您愉快!
#include <stdio.h>
#include <stdlib.h>
void f (void){
int *b = malloc (sizeof(int));
printf ("%p\n", b);
}
int main (){
int i = 0;
while (++i <= 10)
f();
return 0;
}