あなたへの質問は、コードをコンパイルするときに 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'
ほら、あなたはコンパイラを十分に混乱させています:)最適化で5月cmp
を取り除いたのです。always true
:)
エキスパート C プログラミングには (驚き! 驚き!) という名前の章があります。
Chapter 4. ショッキングな真実: C 配列とポインタは同じではない!
強くお勧めします。