c - C 中的指针更改以前的值

标签 c pointers gcc printf

我正在研究 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

结束

在第二部分中,*pa 应该给出 2&(*pa) 应该给出 2686748 但这里以前的值已被更改!

预期输出应为(对于 &(*pa)):2686748、2686748、2、2686748

请解释为什么我没有得到预期的输出以及我哪里出错了??

我故意没有在 printf() 中使用 %p 所以请不要让我用它替换 %u 或 %d。

如果需要,这里是 IDEone 的链接(那里也会生成类似的输出):

程序 - here只需删除/插入注释,您就会明白,首先包括两个 printf,然后或者注释掉其中的一个。

忽略 stdlib.h 的包含我懒得删除它 :P

请尽可能简单:)

程序集:

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

最佳答案

可能是编译器的优化

如果不使用&pa,所有pa的用法等同于&a

因此编译器完全删除了 pa 变量,它不再使用空间。

关于c - C 中的指针更改以前的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19616115/

相关文章:

Python 3.4 Winrandom 编译报错

c - 在非阻塞套接字连接中,select() 总是返回 1

c - bmake : Proper use of Automatic Variables

c - C 中长数计算的错误答案

c++ - 类非静态方法指向全局函数的指针

c - 将几个依赖库链接到我的 "bare metal"C 应用程序中

c - Windows 10 命令提示符下的 assembly-c

arrays - 函数中 int* a 和 int (*a)[N] 的区别?

c - 避免空链表的段错误

c++ - 什么时候函数将在C++中包含堆栈_Unwind_Resume调用?