为什么要投指针?

Dvi*_*aim 1 c pointers casting

我有一个关于C指针和转换的基本问题.
我不明白为什么要施放指针?

我只是尝试了这个代码,我为每个选项获得了相同的输出:

#include <stdio.h>

int main(void)
{
    int x = 3;
    int *y = &x;
    double *s;

    option 1: s = (double*)y;
    option 1: printf("%p, %d\n", (int*)s, *((int*)s));
    option 2: s = y;
    option 2: printf("%p, %d", s, *s);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么我必须这样做s = (double*)y
直观地说,所有变量的地址都是相同的.差异应该是从该地址读取多少字节.此外,关于打印 - 如果我使用%d它将自动采取int.

为什么我需要把它作为一个int*
我错了吗?

chq*_*lie 5

你的问题有很多混乱.int并且double是不同的东西:它们使用不同的位模式表示存储器中的数字,并且在大多数情况下甚至是不同的字节数.当您隐式或显式地要求时,编译器会生成在这些表示之间进行转换的代码:

int x = 3;
double d;

d = x;          // implicit conversion from integer representation to double
d = (double)x;  // explicit conversion generates the same code
Run Code Online (Sandbox Code Playgroud)

这是一个更微妙的例子:

d = x / 2;      // equivalent to d = (double)(x / 2);
Run Code Online (Sandbox Code Playgroud)

将存储的双重代表1进入d.鉴于此:

d = (double)x / 2;  // equivalent to d = (double)x / 2.0;
Run Code Online (Sandbox Code Playgroud)

将存储的双重代表1.5进入d.

投射指针是完全不同的事情.它不是转换,而仅仅是一个转换.您告诉编译器要相信您知道自己在做什么.它不会更改它们指向的地址,也不会影响该地址的内存中的字节.C不允许您将指向int的指针存储到指向double的指针,因为它很可能是一个错误:当您使用错误的类型取消引用指针时,内存的内容被解释为错误的方式,可能会产生不同的值甚至导致崩溃.

你可以通过使用显式强制转换来覆盖编译器的拒绝(double*),但是你要求麻烦.

当您稍后取消引用时s,您可能会访问无效内存,并且读取的值绝对没有意义.

进一步的混淆涉及到printf函数:格式字符串中的格式说明符是程序员关于他作为额外参数传递的实际值类型的承诺.

printf("%p,%d",s,*s)
Run Code Online (Sandbox Code Playgroud)

在这里你传递一个double(没有任何有意义的值),你告诉printf你通过了int.多个未定义行为的明显案例.任何事情都可能发生,包括printf产生与其他选项类似的输出,导致完全混淆.在64位英特尔系统上,双精度和整数传递给printf的方式是不同的,而且非常复杂.

为了避免printf中出现这种错误,请使用-Wall进行编译.gcc和clang会抱怨格式说明符和传递给printf的实际值之间的类型不匹配.

正如其他人所评论的那样,你不应该在C中使用指针强制转换.即使典型的情况int *p = (int *)malloc(100 * sizeof(int))也不需要在C中使用强制转换.