C 什么是void*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

在下面的代码中,指针p如何能无效存储i的地址?printf()中“*(float*)p”的含义是什么


在C void*中,可以指向任何类型的内存位置。您可以将void*指定给int*、double*、char*等类型的变量。通常,void*用于将参数传递给定义时类型未知的函数

但是可以有任何void类型的变量。因此,在取消引用时,必须将void*强制转换为某个指针类型,而不是void*


所以通过
*(float*)p
(未定义)将p(void*type)转换为float*type,然后将其解引用为double(但内存实际上是int)。因此,它在指向的内存中需要浮点型变量。

A
void*
可以存储任何地址。它基本上是一个“广义指针”。您可以将
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);