Reputation:
#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
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
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
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
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