多维数组

时间:2012-08-04 13:33:36

标签: c

#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

也有人可以参考指针及其与多维数组一起使用的好教程。

4 个答案:

答案 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),它是第二个数组/行的第一个元素的地址。

希望这会有所帮助。