C 中 (float *) 和 *(float*) 的区别
Difference between (float *) & *(float*) in C
我正在尝试深入理解指针概念。
在下面的代码中,
#include <stdio.h>
int main()
{
int i = 10;
int *iptr = &i;
printf("(float)* : %f\n", (float)*iptr);
printf("(float*) : %f\n", (float*)iptr);
printf("*(float*) : %f\n", *(float*)iptr);
return 0;
}
输出:
(float)* : 10.000000
(float*) : 10.000000
*(float*) : 0.000000
我还收到了类型转换的警告 (float*)
。
我发现甚至很难分析差异。如果有人能帮我分析一下这三者的具体用法是什么,那将是有帮助的。
区别是
您正在取消引用 int
并将其转换为 float
in
printf("(float)* : %f\n", (float)*iptr);
很好。
您正在将 int
指针转换为 float
指针,并使用 "%f"
说明符打印 float
指针是未定义的行为,打印指针的正确说明符是 "%p"
,所以
printf("(float*) : %f\n", (float*)iptr);
错了,应该是
printf("(float*) : %p\n", (void *) iptr);
casting to float *
这里没有意义,因为void *
地址和float *
地址是一样的,也是int *
地址,区别是当你做指针运算时。
您正在将 int
指针转换为 float
并取消引用生成的 float
指针,尽管它将 violate strict aliasing rules in
printf("(float*) : %f\n", *(float*)iptr);
这也是未定义的行为
第一个正确。
i
是一个 int
变量,iptr
是指向该 int
.
的指针
(float)*iptr
:*iptr
取消引用 iptr
,其中 returns 和 int
。然后 int
被转换为包含相同值的临时 float
。 float
被 printf
使用。
*(float*)iptr
:尝试将指向 int
的指针转换为指向 float
的指针。这是无效的,应该会产生编译器警告或错误。它创建一个具有相同地址的指针,但类型表明它指向 float
值。
*
运算符随后取消引用它,因此 int
被读取为就好像它是 float
。所以得到的 float
将是无效的,并且可能导致段错误,因为 float
s 比 int
s 长,所以它读取的内存比分配给 [=11] 的内存多=].
(float*)iptr
:同样的问题,但它不会解除对(无效)指针的引用,而是将指向 float
的指针传递给 printf
,而不是 float
。但是 printf
期望 float
。某些编译器还应在此处生成 warning/error,因为格式字符串指示预期的值类型。
如果格式说明符指示 %p
,它需要一个指针(void*
、float*
或任何其他)。然后它将打印出地址,而不是它指向的值。例如,这在调试中很有用。
我正在尝试深入理解指针概念。 在下面的代码中,
#include <stdio.h>
int main()
{
int i = 10;
int *iptr = &i;
printf("(float)* : %f\n", (float)*iptr);
printf("(float*) : %f\n", (float*)iptr);
printf("*(float*) : %f\n", *(float*)iptr);
return 0;
}
输出:
(float)* : 10.000000
(float*) : 10.000000
*(float*) : 0.000000
我还收到了类型转换的警告 (float*)
。
我发现甚至很难分析差异。如果有人能帮我分析一下这三者的具体用法是什么,那将是有帮助的。
区别是
您正在取消引用
int
并将其转换为float
inprintf("(float)* : %f\n", (float)*iptr);
很好。
您正在将
int
指针转换为float
指针,并使用"%f"
说明符打印float
指针是未定义的行为,打印指针的正确说明符是"%p"
,所以printf("(float*) : %f\n", (float*)iptr);
错了,应该是
printf("(float*) : %p\n", (void *) iptr);
casting to
float *
这里没有意义,因为void *
地址和float *
地址是一样的,也是int *
地址,区别是当你做指针运算时。您正在将
int
指针转换为float
并取消引用生成的float
指针,尽管它将 violate strict aliasing rules inprintf("(float*) : %f\n", *(float*)iptr);
这也是未定义的行为
第一个正确。
i
是一个 int
变量,iptr
是指向该 int
.
(float)*iptr
:*iptr
取消引用iptr
,其中 returns 和int
。然后int
被转换为包含相同值的临时float
。float
被printf
使用。*(float*)iptr
:尝试将指向int
的指针转换为指向float
的指针。这是无效的,应该会产生编译器警告或错误。它创建一个具有相同地址的指针,但类型表明它指向float
值。*
运算符随后取消引用它,因此int
被读取为就好像它是float
。所以得到的float
将是无效的,并且可能导致段错误,因为float
s 比int
s 长,所以它读取的内存比分配给 [=11] 的内存多=].(float*)iptr
:同样的问题,但它不会解除对(无效)指针的引用,而是将指向float
的指针传递给printf
,而不是float
。但是printf
期望float
。某些编译器还应在此处生成 warning/error,因为格式字符串指示预期的值类型。如果格式说明符指示
%p
,它需要一个指针(void*
、float*
或任何其他)。然后它将打印出地址,而不是它指向的值。例如,这在调试中很有用。