为什么这个循环中的变量会指向同一个内存位置?[重复]

问题描述 投票:-2回答:1

考虑下面的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个不同的地点。如何才能做到这一点?

c pointers
1个回答
8
投票

的范围是 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 会被用来打印一个指针地址。


6
投票

你的代码有未定义的行为。

  • 你不能把一个结构体传递给 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]);
}

6
投票

我认为变量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);
© www.soinside.com 2019 - 2024. All rights reserved.