Путаница с указателем / значением массива - PullRequest
1 голос
/ 08 февраля 2012

Скажем, у нас есть следующий код:

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;
}

При запуске результаты выглядят следующим образом:

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.s и one.eравны - как и ожидалось - но значения не являются.Это то, что смущает меня.

Ответы [ 5 ]

1 голос
/ 08 февраля 2012

one.e - адрес массива one.e.one.s это значение one.s.Если вы хотите получить значение e, вам нужно получить доступ к one.e [0] ... one.e [3].

1 голос
/ 08 февраля 2012

«Значением» массива является адрес первого элемента. Вы можете видеть это в своих результатах. Если вы напечатали:

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

тогда вы должны получить те же ответы.

0 голосов
/ 08 февраля 2012

Компилятор обрабатывает статически размещенные массивы иначе, чем float ptr.Вы можете увидеть это в gcc, скомпилировав с флагом -S.Вот код для первого и второго операторов printf:

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

Вы можете видеть, что есть две инструкции «загрузить эффективный адрес» для первого вызова (& one.s и & one.e), но толькоодна такая команда для второго вызова printf.Команда "leaq -16 (% rbp),% rdx" перемещает адрес% rbp-16 (на 2 байта меньше, чем хранилище адресов в регистре% rbp) в регистр% rdx, где он затем используется printfКоманда для заполнения вывода для one.e.В первой версии эта команда повторяется для загрузки того же адреса в% rcx.

Во второй версии регистр% rcx заполняется командой "movq -16 (% rbp),% rcx",В отличие от «leaq», «movq» - это инструкция для поиска в памяти значения по указанному адресу (% rbp-16).

0 голосов
/ 08 февраля 2012

Массив в любом контексте, кроме операнда оператора & или оператора sizeof, вычисляет адрес своего первого элемента.

Кроме того, ваш код полон неопределенного поведения, потому что вы используете %x для печати указателей. %x допустимо только в том случае, если (повышен) тип переданного выражения: unsigned int.

0 голосов
/ 08 февраля 2012

Значение 'e равно это адрес

Имя массива - это просто маркер для его адреса, поэтому arrayname и &arrayname - это одно и то же

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...