假设我们有以下代码:
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
的地址相同 - 正如预期的那样 - 但值不是。
这让我很困惑。
答案 0 :(得分:1)
数组的“值”是第一个元素的地址。您可以在结果中看到。如果你打印:
printf("vals: one.s = 0x%x, one.e[0] = 0x%x\n",one.s,one.e[0]);
然后你应该得到相同的答案。
答案 1 :(得分:1)
one.e是one.e数组的地址。 one.s是one.s.的值。如果你想要e的值你需要访问one.e [0] ... one.e [3]。
答案 2 :(得分:0)
e 的'值'是它的地址
数组的名称只是其地址的标记,因此arrayname
和&arrayname
是相同的东西
答案 3 :(得分:0)
除&
运算符或sizeof
运算符的操作数之外的任何上下文中的数组都会计算其第一个元素的地址。
此外,您的代码充满了未定义的行为,因为您使用%x
来打印指针。 %x
仅在传递的表达式的(提升的)类型为unsigned int
时有效。
答案 4 :(得分:0)
编译器对静态分配的数组的处理方式与float ptr不同。您可以通过使用-S标志进行编译来在gcc中看到这一点。以下是第一个和第二个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(比%rbp寄存器中的地址存储小2个字节)移动到%rdx寄存器中,然后由printf使用它命令填写one.e的输出。在第一个版本中,重复此命令以将相同的地址加载到%rcx。
在第二个版本中,%rcx寄存器通过“movq -16(%rbp),%rcx”命令填充。与“leaq”不同,“movq”是在内存中为指定地址(%rbp-16)的值执行查找的指令。