C 什么是void*p=&;我
在下面的代码中,指针p如何能无效存储i的地址?printf()中“*(float*)p”的含义是什么C 什么是void*p=&;我,c,pointers,C,Pointers,在下面的代码中,指针p如何能无效存储i的地址?printf()中“*(float*)p”的含义是什么 在C void*中,可以指向任何类型的内存位置。您可以将void*指定给int*、double*、char*等类型的变量。通常,void*用于将参数传递给定义时类型未知的函数 但是可以有任何void类型的变量。因此,在取消引用时,必须将void*强制转换为某个指针类型,而不是void* 所以通过*(float*)p(未定义)将p(void*type)转换为float*type,然后将其解引用为d
在C void*中,可以指向任何类型的内存位置。您可以将void*指定给int*、double*、char*等类型的变量。通常,void*用于将参数传递给定义时类型未知的函数 但是可以有任何void类型的变量。因此,在取消引用时,必须将void*强制转换为某个指针类型,而不是void*
所以通过
*(float*)p
(未定义)将p(void*type)转换为float*type,然后将其解引用为double(但内存实际上是int)。因此,它在指向的内存中需要浮点型变量。Avoid*
可以存储任何地址。它基本上是一个“广义指针”。您可以将void*
回溯到保存到其中的类型,以从中获取有用的类型,并使用它执行诸如指针算术或取消引用指针之类的操作。指针本身不知道它存储什么类型,因此您必须告诉它指向什么类型。由于缺少类型,这很危险,因为记住指针指向的类型是程序员的工作
在你的例子中,你让p
指向i
的地址,这是一个int
,然后你试着把p
的指针打印成float
,而你一开始没有把它分配给float
的地址。这是一种未定义的行为,也是一个很好的例子,说明了无效*
在缺乏经验的人手中的危险
如何使指针p
无效i
的存储地址
空指针可以指向任何数据指针。见此,
简单地使p
指向对象i
的地址。
您可以稍后安全地将其转换回int*
。比如说,
int i = 10;
void *p = &i;
int *j = p; /* j now point to &i */
或者您可以直接铸造p
并使用它:
printf("%d\n", *((int*) p));
这一切都很好
printf()中“*(float*)p”的含义是什么
它试图将int
对象重新解释为float
对象,这是不允许的。在本声明中:
printf("%f\n", *(float *)p);
您正在将p
,一个void*
,转换为float*
,这可能是因为对象p
指向的是一个int
,您正在尝试
将其重新解释为一个float
对象。发件人:
指向对象类型的指针可以转换为指向对象类型的指针
不同的对象类型。如果生成的指针不正确
aligned68)对于引用的类型,行为未定义。
否则,当再次转换回时,结果应相等
指向原始指针。当指向对象的指针转换为
指向字符类型的指针,结果指向最低地址
对象的字节。结果的连续增量,直到
对象的大小,生成指向
反对
这也违反了规则,因为
int*
和float*
是不同的类型,彼此不兼容。将告诉您需要了解的内容。至于存储地址,指针就是这样做的。“如何使指针p无效存储i的地址”-为什么你认为p
不能存储i
的地址?还要注意*(float*)p
是非法的,并且会导致未定义的行为。如果*(float*)p是非法的,我应该在我的代码::块中得到任何错误或警告。但我没有得到任何错误。上面代码的输出是0.000000。@AnjaniKumar不是非法的,它是未定义的。它打破了严格的别名。只有在您从未取消引用此“不同对象类型”指针时,引号才有效。@GillBates否,指针也必须正确对齐。如果不仅仅是赋值导致了未定义的行为。@2501我知道,我刚才说的情况是这样的。即使如此,它仍然在试图解除它。@GillBates那么你应该提到这一点。有时,即使使用不同的类型,也可以取消对指针的引用。但这并不是全部事实。代码违反了严格的别名,因为指针指向不同有效类型的不兼容对象。参见C116.5。对这个问题的任何回答都需要提到代码调用未定义的行为。否则,答案就是误导人们认为代码是好的。
printf("%d\n", *((int*) p));
printf("%f\n", *(float *)p);