在下面的代码中,如何使指针p存储i的地址? " *(浮动*)p"是什么意思?在printf()里面?
#include
void main()
{
int i = 10;
void *p = &i;
printf("%f\n", *(float *)p);
}
答案 0 :(得分:5)
void*
可以存储任何地址。它是一个"广义指针"基本上。您可以将void*
强制转换为保存在其中的类型,以便从中获取有用的类型,并使用指针算法或取消引用指针来执行此操作。指针本身并不知道它存储的类型,因此你必须告诉它它指向的是什么类型。它缺乏类型会使它变得危险,因为程序员的工作就是记住指针指向的类型。
在您的情况下,您将p
指向i
的{{1}}地址,然后您尝试将int
的指针打印为{ {1}}虽然您没有首先将其分配到p
的地址。这是未定义的行为,是没有经验的人float
的危险的一个很好的例子。
答案 1 :(得分:1)
在C void *中可以指向任何类型的内存位置。您可以将void *赋给int *,double *,char * ..等类型的变量。通常void *用于将参数传递给定义时未知的类型的函数。
但是你可以有任何类型为void的变量。因此,在解除引用时,您必须将void *转换为某种指针类型,但不能为void *。
所以通过*(float *)p
(未定义)你将p(它是void *类型)转换为float *类型,然后你将它解引用为double(但内存实际上是int)。所以它期望浮点类型变量在它指向的内存中。
答案 2 :(得分:1)
如何使指针
p
无效存储i
的地址?
void指针可以指向任何数据指针。见C11 draft, 6.3.2.3.所以,
void *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
而你正在尝试
将其重新解释为好像它是int*
个对象。来自undefined:
指向对象类型的指针可以转换为指向a的指针 不同的对象类型。如果结果指针不正确 aligned68)对于引用的类型,行为是未定义的。 否则,当再次转换回来时,结果应该相等 到原始指针。当指向对象的指针转换为 指向字符类型的指针,结果指向最低的地址 对象的字节。结果的连续增量,直到 对象的大小,指向剩余字节的指针 对象
这也违反C11 draft, 6.3.2.3,因为float*
和{{1}}是不同的类型,彼此不兼容。