【发布时间】:2011-03-19 00:13:22
【问题描述】:
我遇到了这段代码:
void incme(double *p)
{
*p += 1;
}
int i = 1;
incme((double *)&i); /* WRONG */
当我尝试执行它时,我得到核心转储。这段代码有什么问题。我们可以不将 int 指针类型转换为 double 类型吗?
谢谢。
【问题讨论】:
标签: c
我遇到了这段代码:
void incme(double *p)
{
*p += 1;
}
int i = 1;
incme((double *)&i); /* WRONG */
当我尝试执行它时,我得到核心转储。这段代码有什么问题。我们可以不将 int 指针类型转换为 double 类型吗?
谢谢。
【问题讨论】:
标签: c
您不是将int 转换为double,而是将int * 转换为double *。如果sizeof(double) 和sizeof(int) 不一样,那就不安全了...
即使您匹配存储大小,您希望输出是什么?浮点类型和整数往往没有任何兼容的表示形式。
【讨论】:
(int) 在 32 位硬件上通常与 4 字节对齐,而 (double) 通常需要 8 字节对齐。如果您的 i 不在 8 字节对齐的地址上,您可以期待 SIGBUS;此外,如果它是在堆栈上分配的,那么较大的(double) 可能会在incme() 返回时覆盖导致核心转储的调用帧,如果前面没有杀死它的话。
【讨论】:
您可以将任何指针从一种类型转换为任何其他类型,但这并不能使其正确。在这种情况下,如果 sizeof(double) != sizeof(int) 那么“incme”中的行很可能会写入分配给“i”整数的内存之外的内存。那么所有的赌注都结束了。
【讨论】:
类型转换和记忆重新解释是有区别的。
您的代码将int * 类型的指针强制转换为double * 类型。这是通过使用显式强制转换来实现的。这个动作本身并不一定会导致任何问题。因此,您在问题标题中所做的假设是不正确的。您观察到的“核心转储”与演员表本身无关。
执行转换后,您将继续取消引用结果指针并访问(修改)它指向的内存。这就是真正的问题发生的时候。代码执行数据重新解释:它尝试将int 类型的对象作为double 类型的对象进行访问。这在 C 语言中总是显式非法的。您观察到的崩溃是由这种重新解释尝试造成的。
所以,对您的问题的简短回答是:您可以当然将指向int 对象的指针转换为double * 类型。但是您不能取消引用生成的double * 指针并访问内存,就好像它拥有一个double 对象一样。
【讨论】:
在大多数平台上,double 为 8 个字节,int 为 4,因此不,您不能将 int* 转换为 double* 并使用它
【讨论】:
一种方法是:
int i = 1;
double d1 = (double)i;
double *d = &d1;
incme(d);
【讨论】: