每次在C中执行程序时指针地址是否会改变?

时间:2016-01-04 18:33:14

标签: c pointers

我试图理解指针,我遇到了这段代码,每当我编译并执行它时,地址就会改变。它是一些垃圾值还是指针实际上是在运行中分配内存?

我的命令提示符:

kaushik@IntelliBox:~/Desktop/Learn_C$ ./Practice
nNUmber is equal to : 15
nNumber is equal to : 25
0xbf98fd64

kaushik@IntelliBox:~/Desktop/Learn_C$ make Practice
make: 'Practice' is up to date.

kaushik@IntelliBox:~/Desktop/Learn_C$ ./Practice
nNUmber is equal to : 15
nNumber is equal to : 25
0xbfcce2a4

kaushik@IntelliBox:~/Desktop/Learn_C$ ./Practice
nNUmber is equal to : 15
nNumber is equal to : 25
0xbfa25df4

kaushik@IntelliBox:~/Desktop/Learn_C$ ./Practice
nNUmber is equal to : 15
nNumber is equal to : 25
0xbfecf104

我的C代码是:

#include <stdio.h>

int main()
{
    int nNumber;
    int *pPointer;

    nNumber = 15;
    pPointer = &nNumber;

    printf("nNUmber is equal to : %d\n", nNumber );

    *pPointer = 25;

    printf("nNumber is equal to : %d\n", nNumber );

    printf("%p\n", pPointer );

    return 0;
}

提前谢谢。

2 个答案:

答案 0 :(得分:4)

表示或确切构成指针值的是实现细节。 C标准没有规定对它的任何要求。每次运行代码时,无法保证值是相同还是不同。

只有有效指针之间的指针算法(例如比较数组对象中的两个指针)才由C标准定义。

顺便说一句,您应该将指针投射到void*以按照C标准的要求使用%p进行打印:

printf("%p\n", (void*) pPointer );

如评论中所述,某些操作系统会address space layout randamization。 Linux默认执行此操作。对于您的代码,我使用ASLR获得以下输出:

$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffde18ba7c
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fff981efe0c
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7ffdade6837c
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7ffced208b4c

如果我禁用它:

echo 0 > /proc/sys/kernel/randomize_va_space

然后输出相同的值:

$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec
$ ./a.out
nNUmber is equal to : 15
nNumber is equal to : 25
0x7fffffffeaec

但就C标准而言,价值绝对无法保证。

答案 1 :(得分:1)

  

它是一些垃圾值还是指针实际上是在运行中分配内存?

都不是。您正在打印的指针值不同,因为指向对象(nNumber)的地址在程序的每次运行中都不同,或者因为使用的指针表示样式为同一地址提供了不同的表示,或两者。在实践中,前者更有可能。

nNumber的地址是程序加载到(虚拟)内存中的函数,没有什么要求从运行到运行一致。实际上,正如Jeff Mercado在评论中所观察到的那样,有一种称为“#34;地址空间布局随机化&#34;在使用时,故意随机化程序和库加载地址,以提高系统安全性。对你的观察来说,它的使用是合理且可能的解释,但它绝不是唯一可能的解释。