当我们声明一个指针时,它指向内存中的某个随机位置或地址,除非我们明确地为其指定一个特定值(任何变量的地址)。
这是代码:
int *p;
printf("int is %p\n",p);
float *j;
printf("float is %p\n",j);
double *dp;
printf("double is %p\n",dp);
char *ch ;
printf("char is %p\n",ch);
j=(float *)p;
printf("cast int to float %p\n",j);
输出:
int is (nil)
float is 0x400460
double is 0x7fff9f0f1a20
char is (nil)
cast int to float (nil)
而不是打印它打印的随机位置(零)
这是什么(零)?我不明白指针的行为吗?
答案 0 :(得分:2)
未初始化的指针变量不指向随机地址。他们指出的地方是不确定的。
在实践中,它们具有堆栈中剩余的价值,您无法确切知道。在您的示例中,这些指针恰好具有0
值,因此它们恰好是空指针,并且它们打印为nil
。
永远不要依赖这种行为。
答案 1 :(得分:1)
如果通过" gnu"标记你的意思是你正在使用glibc,那么原因是glibc中的printf实现将打印"(nil)"遇到NULL指针时。
换句话说,你的几个指针碰巧的值为NULL(0),因为它恰好位于该特定位置的堆栈上。
答案 2 :(得分:0)
详细阐述@yu hao所说的内容:
每当调用子例程时,都会将子帧分配给子例程。此框架一直存在,直到遇到return语句。
子程序经常需要用于存储局部变量值的存储空间,这些变量只在活动子程序中是已知的,并且在返回后不保留值。为此,编译器通过简单地移动堆栈顶部以提供空间来为此用途分配空间。与使用堆空间的动态内存分配相比,这非常快。请注意,子例程的每个单独激活都会在堆栈中为称为“堆栈帧”的本地文件获取其自己的单独空间。
执行此操作的主要原因是跟踪每个活动子例程在完成执行时应返回控制的点。一个活动的子程序是一个已经被调用但尚未完成执行的子程序,之后控制应该被传回到调用点。子例程的这种激活可以嵌套到任何级别(作为特殊情况递归),因此是堆栈结构。例如,如果子程序DrawSquare从四个不同的位置调用子程序DrawLine,则DrawLine必须知道执行完成时返回的位置。为实现此目的,每次调用时,调用指令后面的地址(返回地址)也会被压入调用堆栈。
回到你的问题,在执行过程中,函数可以对其堆栈框架进行更改,当函数“返回”时,其框架从堆栈中“弹出”。
但是在这个过程中堆栈的内容保持不变。只有堆栈指针被修改为指向前一帧。因此,当调用新子例程时,在前一个子程序之上分配新帧,如果子例程具有未初始化的变量,则它们将打印存储在分配给它们的内存中的值。这将取决于那个时间点的堆栈状态。
答案 3 :(得分:-1)
您的所有指针都是nil
/ undefiend
,或者只是堆栈中的随机值!