为什么要投指针?
why to cast pointers?
我有一个关于 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;
}
我的问题是为什么我必须这样做:s = (double*)y
?
直观地说,所有变量的地址都是相同的。区别应该是从这个地址读取多少字节。另外,关于打印 - 如果我使用 %d
它将自动作为 int
.
为什么我需要将其转换为 int*
?
我错了吗?
显式指针转换对于避免编译器警告是必要的。存在指针类型冲突的编译器警告以显示可能的错误。使用指针转换,您可以告诉编译器:"I know what I am doing here..."
你的问题很混乱。 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
这是一个更微妙的例子:
d = x / 2; // equivalent to d = (double)(x / 2);
会将 1
的双重表示存储到 d
中。而这个:
d = (double)x / 2; // equivalent to d = (double)x / 2.0;
将 1.5
的双重表示存储到 d
。
转换指针是完全不同的事情。这不是转换,而只是一种强制。您是在告诉编译器相信您知道自己在做什么。它不会更改它们指向的地址,也不会影响该地址内存中的字节。 C 不允许您将指向 int 的指针存储为指向 double 的指针,因为这很可能是一个错误:当您使用错误的类型取消引用指针时,内存内容被错误地解释,可能会产生不同的值甚至导致崩溃。
您可以通过显式转换为 (double*)
来覆盖编译器的拒绝,但您是在自找麻烦。
稍后解引用s
时,可能会访问无效内存,读取的值肯定没有意义。
进一步的混淆涉及 printf
函数:格式字符串中的格式说明符是程序员关于他作为额外参数传递的实际值类型的承诺。
printf("%p,%d",s,*s)
在这里你传递了一个 double
(没有有意义的值)并且你告诉 printf 你传递了一个 int
。多个未定义行为的公然案例。任何事情都可能发生,包括 printf 产生与其他选项相似的输出,从而导致完全混乱。在 64 位 Intel 系统上,将双精度数和整数传递给 printf 的方式不同且相当复杂。
要避免在printf 中出现这种错误,请使用-Wall 进行编译。 gcc 和 clang 会抱怨格式说明符和传递给 printf 的实际值之间的类型不匹配。
正如其他人评论的那样,您不应该在 C 中使用指针转换。即使是典型的情况 int *p = (int *)malloc(100 * sizeof(int))
也不需要在 C 中进行转换。
我有一个关于 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;
}
我的问题是为什么我必须这样做:s = (double*)y
?
直观地说,所有变量的地址都是相同的。区别应该是从这个地址读取多少字节。另外,关于打印 - 如果我使用 %d
它将自动作为 int
.
为什么我需要将其转换为 int*
?
我错了吗?
显式指针转换对于避免编译器警告是必要的。存在指针类型冲突的编译器警告以显示可能的错误。使用指针转换,您可以告诉编译器:"I know what I am doing here..."
你的问题很混乱。 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
这是一个更微妙的例子:
d = x / 2; // equivalent to d = (double)(x / 2);
会将 1
的双重表示存储到 d
中。而这个:
d = (double)x / 2; // equivalent to d = (double)x / 2.0;
将 1.5
的双重表示存储到 d
。
转换指针是完全不同的事情。这不是转换,而只是一种强制。您是在告诉编译器相信您知道自己在做什么。它不会更改它们指向的地址,也不会影响该地址内存中的字节。 C 不允许您将指向 int 的指针存储为指向 double 的指针,因为这很可能是一个错误:当您使用错误的类型取消引用指针时,内存内容被错误地解释,可能会产生不同的值甚至导致崩溃。
您可以通过显式转换为 (double*)
来覆盖编译器的拒绝,但您是在自找麻烦。
稍后解引用s
时,可能会访问无效内存,读取的值肯定没有意义。
进一步的混淆涉及 printf
函数:格式字符串中的格式说明符是程序员关于他作为额外参数传递的实际值类型的承诺。
printf("%p,%d",s,*s)
在这里你传递了一个 double
(没有有意义的值)并且你告诉 printf 你传递了一个 int
。多个未定义行为的公然案例。任何事情都可能发生,包括 printf 产生与其他选项相似的输出,从而导致完全混乱。在 64 位 Intel 系统上,将双精度数和整数传递给 printf 的方式不同且相当复杂。
要避免在printf 中出现这种错误,请使用-Wall 进行编译。 gcc 和 clang 会抱怨格式说明符和传递给 printf 的实际值之间的类型不匹配。
正如其他人评论的那样,您不应该在 C 中使用指针转换。即使是典型的情况 int *p = (int *)malloc(100 * sizeof(int))
也不需要在 C 中进行转换。