#include <stdio.h>
int multi[2][3] = {{17, 23, 19}, {72, 34, 44}};
int main()
{
printf("%p\n", multi); //line 1
printf("%p\n", *multi); //line 2
if(*multi == multi)
puts("They are equal!");
return 0;
}
第1行和第2行有何不同?
我收到了输出:
They are equal
也有人可以参考指针及其与多维数组一起使用的好教程。
答案 0 :(得分:2)
值相同但类型不同。
multi
的类型为int [2][3]
,评估时会将其转换为int (*)[3]
类型
*multi
的类型为int [3]
,评估后的类型为int *
。
实际上:
*multi == multi
编译器接受,但表达式在C中无效,因为==
运算符的两个操作数的类型不同。要执行比较,您需要转换两个操作数之一。
答案 1 :(得分:2)
在编译代码时,gcc会给出你的答案:
ml.c:10: warning: comparison of distinct pointer types lacks a cast
multi
是一种二维int
数组。那是int[][]
*multi
是一种1维int
数组。那是int[]
这就是他们不是同一个对象的原因。必须投一个人才有资格进行比较。让我们看看这个错误的代码是如何工作的。
令人惊讶的是,根本没有cmp
指令!(使用-g -O0
编译)。实际上你在这里不需要cmp
。因为multi
会被衰减为指向&multi[0][0]
的指针。并且*multi
将被拒绝&multi[0]
。所以从内存的角度来看,它们是相同的,并且c编译器很乐意优化它们(即使使用-O0
:))。
(gdb) disassemble
Dump of assembler code for function main:
0x0000000000400504 <+0>: push rbp
0x0000000000400505 <+1>: mov rbp,rsp
=> 0x0000000000400508 <+4>: mov eax,0x400648
0x000000000040050d <+9>: mov esi,0x600900
0x0000000000400512 <+14>: mov rdi,rax
0x0000000000400515 <+17>: mov eax,0x0
0x000000000040051a <+22>: call 0x4003f0 <printf@plt>
0x000000000040051f <+27>: mov edx,0x600900
0x0000000000400524 <+32>: mov eax,0x400648
0x0000000000400529 <+37>: mov rsi,rdx
0x000000000040052c <+40>: mov rdi,rax
0x000000000040052f <+43>: mov eax,0x0
0x0000000000400534 <+48>: call 0x4003f0 <printf@plt>
0x0000000000400539 <+53>: mov edi,0x40064c
0x000000000040053e <+58>: call 0x400400 <puts@plt>
0x0000000000400543 <+63>: mov eax,0x0
0x0000000000400548 <+68>: leave
0x0000000000400549 <+69>: ret
它在调用puts()
之前所做的唯一事情就是将它应该打印的字符串的地址移动到参数寄存器中。
gdb) x/10cb 0x40064c
0x40064c <__dso_handle+12>: 84 'T' 104 'h' 101 'e' 121 'y' 32 ' ' 97 'a' 114 'r' 101 'e'
0x400654 <__dso_handle+20>: 32 ' ' 101 'e'
你去,你让编译器感到困惑:)它通过cmp
优化剥离了always true
。 :)
专家C编程有一章名为(surprise!surprise!)
第4章令人震惊的真相:C阵列和指针不一样!
强烈推荐。
答案 2 :(得分:0)
使用-Wall编译时,编译器会警告您该行(原因:comparison of distinct pointer types
):
if(* multi == multi)
multi
是数组,在C中,他的地址是他的第一个元素multi[0]
的地址。
*multi
是指向数组的第一个元素的指针,也就是multi [0]。
您正在比较包含相同数据的两个地址:({17, 23, 19}
),它解释了为什么会得到此输出。
希望得到这个帮助。
问候。
答案 3 :(得分:0)
简而言之,在矩阵中,矩阵存储为一系列矩阵行的连续数组:
m具有指向3个int的数组的类型指针 并且是矩阵的第一个数组/行的地址
m *具有指向int的类型指针 并且是第一个的地址 第一行的元素
同样适用于m + 1,它是第二个数组的地址 对于*(m + 1),它是第二个数组/行的第一个元素的地址。
希望这会有所帮助。