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*)
我发现甚至很难分析差异。如果有人能帮我分析一下这三者的具体用法是什么,那将是有帮助的。

区别是

  1. 您正在取消引用 int 并将其转换为 float in

    printf("(float)* : %f\n", (float)*iptr);
    

    很好。

  2. 您正在将 int 指针转换为 float 指针,并使用 "%f" 说明符打印 float 指针是未定义的行为,打印指针的正确说明符是 "%p",所以

    printf("(float*) : %f\n", (float*)iptr);
    

    错了,应该是

    printf("(float*) : %p\n", (void *) iptr);
    

    casting to float *这里没有意义,因为void *地址和float *地址是一样的,也是int *地址,区别是当你做指针运算时。

  3. 您正在将 int 指针转换为 float 并取消引用生成的 float 指针,尽管它将 violate strict aliasing rules in

    printf("(float*) : %f\n", *(float*)iptr);
    

    这也是未定义的行为

第一个正确。

i 是一个 int 变量,iptr 是指向该 int.

的指针
  1. (float)*iptr*iptr 取消引用 iptr,其中 returns 和 int。然后 int 被转换为包含相同值的临时 floatfloatprintf 使用。

  2. *(float*)iptr:尝试将指向 int 的指针转换为指向 float 的指针。这是无效的,应该会产生编译器警告或错误。它创建一个具有相同地址的指针,但类型表明它指向 float 值。

    * 运算符随后取消引用它,因此 int 被读取为就好像它是 float。所以得到的 float 将是无效的,并且可能导致段错误,因为 floats 比 ints 长,所以它读取的内存比分配给 [=11] 的内存多=].

  3. (float*)iptr:同样的问题,但它不会解除对(无效)指针的引用,而是将指向 float 的指针传递给 printf,而不是 float。但是 printf 期望 float。某些编译器还应在此处生成 warning/error,因为格式字符串指示预期的值类型。

    如果格式说明符指示 %p,它需要一个指针(void*float* 或任何其他)。然后它将打印出地址,而不是它指向的值。例如,这在调试中很有用。