Rakesh_Kumar
Rakesh_Kumar

Reputation: 1442

structure array memory arrangement

struct abc filled[]={{"aa",10},{"bb",20}};    
   printf("[%u,%u]\n",filled,&filled);
   printf("[%u,%u]\n",filled[0],&filled[0]);

   printf("[%u,%u]\n",filled+1,&filled+1);
   printf("[%u,%u]\n",filled[1],&filled[1]);

how the filled array is arranged in memory? filled being the name of array returns the base address of the array...similarly &filled. but filled[0] gives some unknown value, may be the address and the googly part is &filled[0] which gives the value 10. I am not able to get the logic. following is the output i am getting

[2293552,2293552]    
[4206592,10]    
[2293560,2293568]    
[4206595,20]    

Upvotes: 0

Views: 264

Answers (2)

kfsone
kfsone

Reputation: 24249

Your code

struct abc filled[]={{"aa",10},{"bb",20}};    
printf("[%u,%u]\n",filled,&filled);
printf("[%u,%u]\n",filled[0],&filled[0]);

Before we can discuss this any further, we need to have some idea of what "struct" looks like. You didn't provide a definition so I'm going to assume it is something like

struct abc {
    const char* str;
    int i;
};

So filled is an array of these objects:

filled[] = {
    struct abc { str = "aa", i = 10 },
    struct abc { str = "bb", i = 20 }
};

filled[0] refers to the first struct abc in the space.

{ str = "aa", i = 10 }

In memory, in a 32-bit build, these will be laid out, with [...] representing a byte:

[ptr][ptr][ptr][ptr][i][i][i][i]

On a 64-bit system, these will be laid out as

[ptr][ptr][ptr][ptr][ptr][ptr][ptr][ptr][i][i][i][i]

The exact order of the bytes that make up str and i will depend on the architecture.

Now, your code...

struct abc filled[]={{"aa",10},{"bb",20}};    
printf("[%u,%u]\n",filled,&filled);
printf("[%u,%u]\n",filled[0],&filled[0]);

printf has a limitation. The underlying function cannot actually see your arguments - it just gets data on a stack and it uses the print format as a guide.

Ultimately what's going horribly wrong is that you are passing a struct as a printf argument.

printf("[%u,%u]", filled[0], &filled[0]);

filled[0] resolves to a struct abc.

What's happening is that the program is putting the value of filled[0] onto the stack for printf to use. The first %u in the format mask consumes the str component and the second consumes the i.

If this is your complete program:

#include <stdio.h>

struct abc {
    const char* str;
    int i;
};

int main() {
    struct abc filled[] = { { "aa", 16 }, { "bb", 20 } };
    printf("filled = %p\n", filled);
    printf("&filled = %p\n", &filled);
    printf("filled[0] = %p\n", filled[0]);
    printf("&filled[0] = %p\n", &filled[0]);
    printf("filled[0].str = %p\n", filled[0].str);
    printf("filled[0].i = %d\n", filled[0].i);
    return 0;
}

Here is the output:

filled = 0xbfba5cb0
&filled = 0xbfba5cb0
filled[0] = 0x80485b0     <--+
&filled[0] = 0xbfba5cb0      | filled[0] actually printed the .str value
filled[0].str = 0x80485b0 <--+
filled[0].i = 16

What you are missing is the following compiler warning, because you're compiling with Visual Studio or without -Wall:

prog.c: In function ‘main’:
prog.c:12:5: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘struct abc’ [-Wformat=]
     printf("filled[0] = %p\n", filled[0]);

When you do

printf("[%u, %u]\n", filled[0], &filled[0]);

The program does the following:

push stack (const char*) "[%u, %u]\n"   // in 32-bit, 4-bytes of pointer.
push stack (struct abc) filled[0]       // pushes the entire of filled[0], str and i, 8 bytes.
push stack (struct abc*) &filled[0]     // pushes another 4 bytes.

And the resulting stack looks like this

enter image description here

printf never uses the value of "&filled[0]" because you didn't specify the right formats to read the data on the stack. If you instead used

printf("filled[0].str=%p, filled[0].i=%u, &filled[0]=%p\n", filled[0], &filled[0]);

then you would get more meaningful data, but this is a dangerous way to achieve the result because it makes a lot of assumptions about data layout and the stack.

Fundamentally, your problem is that you are doing this:

printf("%u", filled[0]);

where filled[0] is not a simple datatype.

Upvotes: 2

AnT stands with Russia
AnT stands with Russia

Reputation: 320361

Format specifier %u in printf requires an argument of type unsigned int. You are supplying it with arguments of completely unrelated types: pointers and objects of struct type. Because of this your code exhibits undefined behavior. The code is broken and its output is completely meaningless. There's not much point in trying to analyze or explain it. (The explanation certainly exists, but it has nothing to do with the primary question.)

As for how arrays are arranged in memory... StackOverflow is choke-full of repetitive answers to this very question. Just do a search.

Upvotes: 3

Related Questions