学习有关空指针的知识,并越过了该程序。在这里,我声明了void指针,并尝试访问void双指针,并且工作正常。这里无法理解C逻辑。有人可以帮忙吗?谢谢。
#include<stdio.h>
int main()
{
int i = 5,*ptr;
ptr= &i;
void *vptr;
vptr = &ptr;
printf("\nValue of iptr = %d %d %d", **(int **)vptr, **(int ***)vptr, **(int ****)vptr);
return 0;
}
op:
Value of iptr = 5 5 5
这似乎很奇怪,但是从语言的角度来看是完全合法的,即使它以明显的方式表明了语言的某些局限性。在这种情况下,wrong强制转换将导致编译器未检测到UB,并给出错误的输出为有效。
您将vptr
定义为指向void指针的指针,因此回头对其进行解引用,就可以得到指向值为5的int
的指针。
然后在示例代码中,您cast vptr
成为指向指针的指针……等等,但是您仅打印第二次取消引用,恰好是找到的值:5您解释为整数。
实际上,编译器正在显示所谓的第二指针值,并将值5解释为地址。
编译器还应该发出有关printf
中类型不匹配的警告(您应该将%p
与指针一起使用。
如果您尝试更多的取消引用,将出现预期的访问冲突。
尝试
printf("\nValue of iptr = %d", ***(int ***)vptr);
在第二次取消引用之后,您尝试在内存地址0x00000005读取。
注意:应用强制转换,除非对于不兼容的类型,否则您将[[impose”提交给编译器,以将强制转换对象视为强制转换类型的对象。该语言不会执行任何检查,并且会盲目遵循您的指示。如果您告诉编译器在该位置期望一个指针,则它将根据实际位置独立地期望一个指针。
int a = 10;
int* p = &a;
printf("%d", p); // <-- this will print the value of p which is the address of a.
printf("%d", *p); // <-- this will print the value of a.
在您的情况下,编译器可能会发出警告,告诉您%d
期望类型为int
,但被赋予类型为int*
。第一次调用
printf
将使第二个参数作为int
(**(int**)vptr
)传递。所以这里没有错。第二个调用将把第二个参数作为
int*
传递,但是,正如我在上面的示例中所解释的,当您传递一个指针时,您传递了它的值。您可以这样看:
printf("%d", (int*) (**(int**)vptr) );
"%d"
的printf
需要一种int
类型,因此,即使您具有printf("%d", (int*)5)
,它仍会打印5
。实际上,您可以给它任何类型,并且仍将其视为int。您可以拨打以下电话:
printf("%d", (int**) 10 ); printf("%d", (char*) 10 ); printf("%d", (float*) 10 ); printf("%d", (void*) 10 ); // ... and so on
上述所有呼叫将打印10,对于与int
具有相同大小的所有类型,将打印10。