Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the variable in this loop point at the same memory location? [duplicate]

Tags:

c

pointers

Consider the below C code. I would have thought that the variable bar was being instantiated every time and would thus point to different addresses in memory, but it doesn't.

for (i = 2; i < 7; i++) {
    struct foo bar;
    printf("struct %u\n", bar);
}

Output:

struct 13205520
struct 13205520
struct 13205520
struct 13205520
struct 13205520

In case it is not obvious, what I want is to generate 5 different structs—well, actually 5 different pointers to structs—at 5 different locations. How can I do this?

like image 459
Lucky Avatar asked May 03 '20 19:05

Lucky


People also ask

What is a variable that points to a memory location?

A pointer variable is a variable (a name that references some area of memory), but what's in that area of memory? What's the pointer itself? Well, it's a memory address, a way of referencing another memory location.

Can two variables have the same memory address?

You cant have variables stored in the same memory address. You can point to a memory address and store the value in that memory address to a different memory address. No YOU are wrong, that is not 2 variables at the same address, that is a variable and a reference to the same variable. A reference is not a variable.

Is it possible that two or more than two variables hold the address of same memory location?

Yes, two or more references, say from parameters and/or local variables and/or instance variables and/or static variables can all reference the same object.


2 Answers

The scope of bar only exists within one iteration of the loop. That means that when the next struct foo is created, it will be put in the same place as the old bar, because as far as the compiler sees it, the bar is no longer necessary. Looking at your example, it doesn't seem like you need to handle all of the bar's at once. So you might be okay with them all being at the same location. However, if you need to deal with multiple at a time, I can think of two possible solutions.

Putting the scope outside of the loop

To do this, you'll need an array of struct foo's. The scope of the array needs to be outside of the loop. For example:

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
}

Then each iteration of your for loop can modify one of the values

Allocating on the heap

If you're okay with storing five pointers in memory, you can allocate each bar somewhere on the heap. You would probably end up just using an array anyway, so this would probably only be useful if you needed to return the structs into another function. You'd need to do something like this:

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
}

It's also worth mentioning, as someone else pointed out, that %p would be used to print a pointer address.

like image 104
Botahamec Avatar answered Sep 30 '22 06:09

Botahamec


Your code has undefined behavior:

  • you cannot pass a structure to printf to print its address, the conversion specifier %u expects an unsigned int, not a structure.
  • furthermore, bar is uninitialized, passing it has undefined behavior.
  • each iteration instantiates a new structure that is uninitialized, possibly at the same location and it goes out of scope as soon as you leave the for body for the next iteration.
  • to print the location of the structure, use %p and pass (void *)&bar, but it is unspecified whether the address of bar will be the same for each iteration or not.

Most compilers will reuse the same space for bar at each iteration, but a compiler could conceivably generate code to randomise the address of bar in a proprietary way in order to make the code more resilient to exploits.

If you want all structures to reside in different addresses, you can define an array of structures outside the scope of the loop and print their addresses this way:

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]);
}
like image 30
chqrlie Avatar answered Sep 30 '22 06:09

chqrlie