不要让*zippo
去到15号位置然后找到该位置的值。
如果是这样的话,那么printf(" * ((int **) zippo) = %p\n", * ((int **) zippo) );
将会输出与printf(" *zippo = %p\n", *zippo);
相同的内容,但事实并非如此。
当我运行这段代码时,我得到了以下结果:
#include <stdio.h>
int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};
int main(){
printf("zippo[0] = %p\n", (void *) (zippo[0]) );
printf(" zippo = %p\n", (void *) zippo);
printf(" *zippo = %p\n", (void *) (*zippo) );
printf(" **zippo = %d\n", (int) ( **zippo) );
printf(" * ((int **) zippo) = %p\n", (void *) (* ((int **) zippo) ));
}
这是我得到的:
zippo = 0x804a040
*zippo = 0x804a040
**zippo = 2
* ((int **) zippo) = 0x2
我使用 gcc -Wall -Wextra -Wpedantic -pedantic
编译了这段代码,以确保没有警告被隐藏,并使用选项 -m32
来获得 32 位地址(与 int 相同大小)。
实际上,我很难理解其中发生了什么,所以我决定查看相应的汇编代码。使用 gcc -S file.c -o file.s
我得到了以下结果。
第一个变量声明:
.globl zippo
.data
.align 32
.type zippo, @object
.size zippo, 32
zippo:
.long 2
.long 4
.long 6
.long 8
.long 1
.long 3
.long 5
.long 7
.section .rodata
.LC0:
.string "zippo[0] = %p\n"
.LC1:
.string " zippo = %p\n"
.LC2:
.string " *zippo = %p\n"
.LC3:
.string " **zippo = %d\n"
.LC4:
.string " * ((int **) zippo) = %p\n"
printf("zippo[0] = %p\n", (void *) (zippo[0]) );
的相应汇编代码为:
movl $zippo, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
printf(" zippo = %p\n", (void *) zippo);
的相应汇编代码为:
movl $zippo, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
printf(" *zippo = %p\n", (void *) (*zippo) );
的相应汇编代码为:
movl $zippo, %esi
movl $.LC2, %edi
movl $0, %eax
call printf
printf(" **zippo = %d\n", (int) ( **zippo) );
的相应汇编代码为:
movl $zippo, %eax
movl (%rax), %eax
movl %eax, %esi
movl $.LC3, %edi
movl $0, %eax
call printf
关于 printf(" * ((int **) zippo) = %p\n", (void *) (* ((int **) zippo) ));
的相应汇编代码如下:
movl $zippo, %eax
movq (%rax), %rax
movq %rax, %rsi
movl $.LC4, %edi
movl $0, %eax
call printf
正如您在这里所注意到的,对于前三个printf,相应的汇编代码完全相同(变化的是LCx,它对应于格式)。
最后2个printf也是一样的。
我的理解是,由于编译器知道
zippo 是一个二维数组,因此知道 * zippo 是一个一维数组,其数据从第一个元素的地址开始。
int **
)已经有上百个问题了。你为什么期望可以使用完全不同的类型呢?如果你有一个int
,你不能用printf
来打印_Complex
! - too honest for this site