私はCでポインターを調べていたところ、さまざまなケースを作成していたときに、これに出くわしました:(IDEを使用 - Code::Blocks
コンパイラ - GNU GCC)
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a=2;
int *pa;
pa=&a;
printf("1 %u\n", &a );
printf("2 %u\n", pa );
printf("3 %d\n", a );
printf("4 %u\n", &(pa));
//printf("\n4 %u\n", &(*pa)); // output not as expected
printf("End \n");
return 0;
}
出力は次のとおりです。
1 2686748
2 2686748
3 2
4 2686744
終わり
ここで、4 番目の printf を次のように変更します。
printf("\n4 %u\n", &(*pa));
出力は次のように変わります。
1 2686744
2 2686744
3 2
4 2686744
終わり
ここで 2 番目の部分では、*pa は2を指定し、&(*pa)は2686748を指定する必要がありますが、ここでは前の値が変更されています!
予想される出力は次のようになります (&(*pa) の場合): 2686748、2686748、2、2686748
期待される出力が得られない理由と、どこで間違っているのか説明してください??
私は意図的に printf() で %p を使用していないので、%u や %d をそれに置き換えるように頼まないでください。
必要に応じて、IDEone へのリンクを次に示します (同様の出力がそこでも生成されます)。
プログラム -ここでは、コメントを削除/挿入するだけで理解できます。最初に両方の printf を含め、代わりにそのうちの 1 つをコメントアウトします。
stdlib.h のインクルードを無視する
できるだけシンプルにしてください:)
アセンブリ:
First for:
printf("4 %u\n", &(pa));
// printf("\n4 %u\n", &(*pa));
0x00401334 push %ebp
0x00401335 mov %esp,%ebp
0x00401337 and $0xfffffff0,%esp
0x0040133A sub $0x20,%esp
0x0040133D call 0x401970 <__main>
0x00401342 movl $0x2,0x1c(%esp)
0x0040134A lea 0x1c(%esp),%eax
0x0040134E mov %eax,0x18(%esp)
0x00401352 lea 0x1c(%esp),%eax
0x00401356 mov %eax,0x4(%esp)
0x0040135A movl $0x403024,(%esp)
0x00401361 call 0x401be8 <printf>
0x00401366 mov 0x18(%esp),%eax
0x0040136A mov %eax,0x4(%esp)
0x0040136E movl $0x40302a,(%esp)
0x00401375 call 0x401be8 <printf>
0x0040137A mov 0x1c(%esp),%eax
0x0040137E mov %eax,0x4(%esp)
0x00401382 movl $0x403030,(%esp)
0x00401389 call 0x401be8 <printf>
**here>** 0x0040138E lea 0x18(%esp),%eax
0x00401392 mov %eax,0x4(%esp)
0x00401396 movl $0x403036,(%esp)
0x0040139D call 0x401be8 <printf>
0x004013A2 movl $0x40303c,(%esp)
0x004013A9 call 0x401be0 <puts>
0x004013AE mov $0x0,%eax
0x004013B3 leave
0x004013B4 ret
Second for :
// printf("4 %u\n", &(pa));
printf("\n4 %u\n", &(*pa));
0x00401334 push %ebp
0x00401335 mov %esp,%ebp
0x00401337 and $0xfffffff0,%esp
0x0040133A sub $0x20,%esp
0x0040133D call 0x401970 <__main>
0x00401342 movl $0x2,0x18(%esp)
0x0040134A lea 0x18(%esp),%eax
0x0040134E mov %eax,0x1c(%esp)
0x00401352 lea 0x18(%esp),%eax
0x00401356 mov %eax,0x4(%esp)
0x0040135A movl $0x403024,(%esp)
0x00401361 call 0x401be8 <printf>
0x00401366 mov 0x1c(%esp),%eax
0x0040136A mov %eax,0x4(%esp)
0x0040136E movl $0x40302a,(%esp)
0x00401375 call 0x401be8 <printf>
0x0040137A mov 0x18(%esp),%eax
0x0040137E mov %eax,0x4(%esp)
0x00401382 movl $0x403030,(%esp)
0x00401389 call 0x401be8 <printf>
**here>** 0x0040138E mov 0x1c(%esp),%eax
0x00401392 mov %eax,0x4(%esp)
0x00401396 movl $0x403036,(%esp)
0x0040139D call 0x401be8 <printf>
0x004013A2 movl $0x40303d,(%esp)
0x004013A9 call 0x401be0 <puts>
0x004013AE mov $0x0,%eax
0x004013B3 leave
0x004013B4 ret
Third one for:
printf("4 %u\n", &(pa));
printf("\n4 %u\n", &(*pa));
0x00401334 push %ebp
0x00401335 mov %esp,%ebp
0x00401337 and $0xfffffff0,%esp
0x0040133A sub $0x20,%esp
0x0040133D call 0x401980 <__main>
0x00401342 movl $0x2,0x1c(%esp)
0x0040134A lea 0x1c(%esp),%eax
0x0040134E mov %eax,0x18(%esp)
0x00401352 lea 0x1c(%esp),%eax
0x00401356 mov %eax,0x4(%esp)
0x0040135A movl $0x403024,(%esp)
0x00401361 call 0x401bf8 <printf>
0x00401366 mov 0x18(%esp),%eax
0x0040136A mov %eax,0x4(%esp)
0x0040136E movl $0x40302a,(%esp)
0x00401375 call 0x401bf8 <printf>
0x0040137A mov 0x1c(%esp),%eax
0x0040137E mov %eax,0x4(%esp)
0x00401382 movl $0x403030,(%esp)
0x00401389 call 0x401bf8 <printf>
0x0040138E lea 0x18(%esp),%eax
0x00401392 mov %eax,0x4(%esp)
0x00401396 movl $0x403036,(%esp)
0x0040139D call 0x401bf8 <printf>
**here>** 0x004013A2 mov 0x18(%esp),%eax
0x004013A6 mov %eax,0x4(%esp)
0x004013AA movl $0x40303c,(%esp)
0x004013B1 call 0x401bf8 <printf>
0x004013B6 movl $0x403043,(%esp)
0x004013BD call 0x401bf0 <puts>
0x004013C2 mov $0x0,%eax
0x004013C7 leave
0x004013C8 ret