1

Say we have the following code:

typedef union {
   float    e[4];
   __v4sf   v;
   float    *s;
} __vec4f;

float test[12];


int main(){ 
__vec4f one;

printf("adrs: &one.s = 0x%x, &one.e = 0x%x\n", &one.s, &one.e);
printf("vals: one.s = 0x%x, one.e = 0x%x\n",one.s,one.e);
one.s = test;
printf("adrs: &one.s = 0x%x, &one.e = 0x%x\n", &one.s, &one.e);
printf("vals: one.s = 0x%x, one.e = 0x%x\n",one.s,one.e);

return 0;
}

When running the results are like follows:

adrs: &one.s = 0xbffff270, &one.e = 0xbffff270
vals: one.s = 0x927ff590, one.e = 0xbffff270
adrs: &one.s = 0xbffff270, &one.e = 0xbffff270
vals: one.s = 0x52a0, one.e = 0xbffff270

One sees that the address of one.s and one.e are equal - as expected - but the values aren't. This is what confuses me.

1
  • Under memory they are the same, but their interpretation is quite different Commented Feb 8, 2012 at 16:53

5 Answers 5

1

one.e is the address of the one.e array. one.s is the value of one.s. If you want the value of e you need to access one.e[0]...one.e[3].

Sign up to request clarification or add additional context in comments.

Comments

1

The "value" of an array is the address of the first element. You can see that in your results. If you printed:

printf("vals: one.s = 0x%x, one.e[0] = 0x%x\n",one.s,one.e[0]);

then you should get the same answers.

Comments

0

The 'value' of e is it's address

The name of an array is just a marker for it's address so arrayname and &arrayname are the same thing

Comments

0

An array in any context except the operand of the & operator or the sizeof operator evaluates to the address of its first element.

Moreover your code is full of undefined behavior because you are using %x to print pointers. %x is only valid if the (promoted) type of the expression passed is unsigned int.

Comments

0

The compiler treats statically allocated arrays differently than a float ptr. You can see this in gcc by compiling with the -S flag. Here is the code for the first and second printf statements:

printf("adrs: &one.s = 0x%x, &one.e = 0x%x\n", &one.s, &one.e);
    movl    $.LC0, %eax
    leaq    -16(%rbp), %rdx
    leaq    -16(%rbp), %rcx
    movq    %rcx, %rsi
    movq    %rax, %rdi
    movl    $0, %eax
    call    printf

printf("vals: one.s = 0x%x, one.e = 0x%x\n",one.s,one.e);
    movq    -16(%rbp), %rcx
    movl    $.LC1, %eax
    leaq    -16(%rbp), %rdx
    movq    %rcx, %rsi
    movq    %rax, %rdi
    movl    $0, %eax
    call    printf

You can see that there are two "load effective address" instructions for the first call (&one.s and &one.e), but only one such command for the second printf call. The "leaq -16(%rbp), %rdx" command moves the address %rbp-16 (2 bytes less than the the address store in the %rbp register) into the %rdx register, where it is then used by the printf command to fill in the output for one.e. In the first version, this command is repeated to load the same address into %rcx.

In the second version, the %rcx register is populated via the "movq -16(%rbp), %rcx" command. Unlike "leaq", "movq" is an instruction to perform a lookup in memory for the value at the address specified (%rbp-16).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.