考虑下面的C代码。我本以为变量 bar
每次都会被实例化,因此会指向内存中不同的地址,但事实并非如此。
for (i = 2; i < 7; i++) {
struct foo bar;
printf("struct %u\n", bar);
}
输出。
struct 13205520
struct 13205520
struct 13205520
struct 13205520
struct 13205520
如果不是很明显的话,我想生成5个不同的... struct
其实有5个不同的指针,可以指向 struct
在5个不同的地点。如何才能做到这一点?
的范围是 bar
只存在于循环的一次迭代中。这意味着,当下一个 struct foo
创建,它将被放在与旧的 bar
,因为在编译器看来,这个 bar
已经没有必要了。从你的例子来看,你似乎不需要处理所有的 bar
的一次。所以,你可能会同意他们都在同一个位置。然而,如果您需要一次处理多个,我可以想到两种可能的解决方案。
要做到这一点,你需要一个数组的 struct foo
's. 数组的范围需要在循环之外。比如说。
struct foo bar_list[5];
for (i = 2; i < 7; i++) {
printf("struct %p\n", (void *)&bar_list[i - 2]);
// use the foo's here
}
那么你的for循环的每一次迭代都可以修改其中一个值。
如果你不介意在内存中存储五个指针,你可以在堆上某个地方分配每个条形结构。你可能最终还是会使用一个数组,所以这可能只有在你需要将结构返回到另一个函数中时才会有用。你需要做这样的事情。
struct foo* bar_list[5];
for (i = 2; i < 7; i++) {
bar_list[i - 2] = malloc(sizeof(struct foo));
printf("struct %p\n", (void *)bar_list[i - 2]);
// do anything else you need to do
}
还值得一提的是,正如有人指出的,那就是 %p
会被用来打印一个指针地址。
你的代码有未定义的行为。
printf
打印其地址,转换指定器 %u
期待一个 unsigned int
,而不是一个结构。bar
是未初始化的,传递它有未定义的行为。for
的主体,用于下一次迭代。%p
并通过 (void *)&bar
的地址,但未明确说明是否为 "我"。bar
是否会在每次迭代中使用相同的空间。大多数编译器都会为 bar
的地址,但可以想象编译器可以生成随机的代码,在每次迭代的时候,对 bar
的专有方式,以使代码更有弹性。
如果你想让所有的结构驻留在不同的地址,你可以在循环的范围外定义一个结构的数组,然后这样打印它们的地址。
struct foo bar[5];
for (int i = 2; i < 7; i++) {
printf("address of struct bar[%d] is %p\n", i - 2, (void *)&bar[i - 2]);
}
我认为变量bar每次被实例化的时候
是的,只是它不是 实例化只是编译器为它预留了一些内存,或者你的程序表现为 仿佛 它确实为它预留了一些内存。
因此会指向内存中不同的地址
这将是错误的。C只保证对象在它们的 寿命. 您的 bar
有 自动存储期的时候,它的寿命就结束了。}
在块的最后。
有 两种 的方法来逃避这个问题。
分配一个 阵列 的 struct foo
的存储时间比for循环的存储时间长;现在你可以使用 i
来索引这个数组。
使用动态内存分配与 malloc
- 所分配的存储持续时间保证了对象的存活,直到内存被deallocated为止。free
.
请注意,使用下列词语是不恰当的
printf("struct %u\n", bar);
%u
期待一个 unsigned int
但你传入的是一个结构体。构造体的行为是未定义的,而且实际上我们无法知道这个数字的意义是什么 13205520
是或来自哪里。
要打印地址的 bar
你 必须使用
printf("struct %p\n", (void *)&bar);