void * p =& i是什么意思?

时间:2016-11-18 09:52:44

标签: c pointers

在下面的代码中,如何使指针p存储i的地址? " *(浮动*)p"是什么意思?在printf()里面?

#include
void main()
{
  int i = 10;
  void *p = &i;
  printf("%f\n", *(float *)p);
}

3 个答案:

答案 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}}是不同的类型,彼此不兼容。