user1547436
user1547436

Reputation:

Multi dimensional Arrays

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

How line 1 and 2 is different?

I'm getting output :

They are equal

Also can somebody refer a good tutorial on pointers and its use with multidimensional arrays .. .

Upvotes: 2

Views: 245

Answers (4)

GionJh
GionJh

Reputation: 2894

In brief in C a matrix is stored as a series of consecutive arrays wich are the rows of the matrix :

m has type pointer to array of 3 ints and is the address of the first array / row of the matrix

m* has type pointer to int and is the address of the first element of the first row

the same apply to m+1 wich is the address of the second array and for *( m + 1 ) wich is the address of the first element of the second array/row.

hope this helps.

Upvotes: 0

Aftnix
Aftnix

Reputation: 4589

The question to you your answer is given by gcc when you compile your code:

ml.c:10: warning: comparison of distinct pointer types lacks a cast

multi is a type of 2 dimensional int array. that is int[][]

Where *multi is a type of 1 dimensional int array. That is int[]

That's why they are not the same object. One has to be cast to be eligible for comparison. Lets see how this wrong code works under the hood.

Surprisingly there's no cmp instruction at all!(compiled with -g -O0). Actually you don't need a cmp here. Because multi will be decayed to a pointer to &multi[0][0]. and *multi will be decayed to &multi[0]. So from the memory's point of view, they are the same, and c compiler happily optimizes them (even with -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

only thing its doing before calling puts() is moving the address of the string which it should print into argument register.

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'

There you go, you are confusing the compiler enough :) that it stripped away the cmp may with a always true optimization. :)

Expert C programming has a chapter named (surprise! surprise!)

Chapter 4. The Shocking Truth: C Arrays and Pointers Are NOT the Same!

Highly recommended.

Upvotes: 2

TOC
TOC

Reputation: 4446

When you compile with -Wall, the compiler will warn you about the line (cause: comparison of distinct pointer types):

if(*multi == multi)

multi is array and in C his address is the address of his first element aka multi[0]. *multi is pointer to the first element of the array aka multi[0].

You are comparing two addresses that contain the same data: ({17, 23, 19}), which explain why you get this output.

Hope this help.

Regards.

Upvotes: 0

ouah
ouah

Reputation: 145829

The value is the same but the type is different.

multi is of type int [2][3] and when evaluated it is converted to the type int (*)[3]

*multi is of type int [3] and when evaluated it is of type int *.

Actually:

*multi == multi

is accepted by your compiler but the expression is not valid in C because the two operands of the == operators are of different types. To perform the comparison you would need to cast one of the two operands.

Upvotes: 2

Related Questions