【问题标题】:why is this pass by pointer is not working as intended?为什么这个按指针传递没有按预期工作?
【发布时间】:2015-11-04 17:34:35
【问题描述】:

我正在尝试了解为什么以下代码不起作用...请帮助:

void incme(double *p)
{
    printf("%x,%x\n",p,*p);
    *p = *p + 1;
    printf("%x,%x\n",p,*p);
}
int main()
{
    int i = 1;
    incme((double *)&i);    
    printf("%x,%x",&i,i);
}

输出是:

ff99a348,1
ff99a348,1
ff99a348,1

我期待: ff99a348,1 ff99a348,2 ff99a348,2
它打破了我对指针的了解......

谢谢。

编辑:

我要问的主要问题是 incme((double *)&i);为什么不将其转换为加倍并将其传递给函数? ...抱歉没有指出eailer ....

【问题讨论】:

  • int和double的大小不一样
  • 第一步:获取decent book on C,第二步:阅读。
  • incme((double *)&i)中的类型转换;将 int 转换为 double 吗?
  • 类型转换会将int* 转换为double*,这会导致C 的所有规则都失效,因为实际上不允许您这样做。

标签: c pointers pass-by-pointer


【解决方案1】:

当您使用*p = *p + 1; 和 p 蜂鸣 double* 时,实际上,当您使用 printf 将其显示为整数时,使用自定义格式 (wiki) 表示双精度数之后,该地址处内存的内部表示发生了变化(变为双重表示),这就是您获得这样结果的原因。

我运行了代码,得到如下输出:

205afc2c,205afd28
205afc2c,593b4ab0
205afc2c,0

它显示使用该值作为双精度值无效,并且当它增加时,它不会更新双精度值的 sizeof(int) 第一位(因为它在最后一行打印 0)。

希望我说清楚了!

编辑

我稍微更改了代码以向您展示实际发生的情况:

void incme(double *p)
{
    printf("%x,%lf\n",p,*p);
    *p = *p + 1;
    printf("%x,%lf\n",p,*p);
}
int main()
{
    int i = 1;
    incme((double *)&i);    
    printf("%x, %lf, %d",&i,i, i);
}

给我以下输出:

cb90990c,0.000000
cb90990c,1.000000
cb90990c, 1.000000, 0

如您所见,如果您将它们打印为 double,则该值确实是正确的(但 1.0000 的二进制表示不是 00000000001,正如我之前所说,这就是为什么十六进制格式会给您一个很大的数字)。 回到主界面,如果将值显示为双精度值(如果 i 应该是 int 则为事件),因为 incme 函数更改了它的内存布局,它确实打印了 1.0000,但内存的前 32 位在此地址为 0,因此将其打印为 int 为您提供 0。

【讨论】:

  • 所以函数中的类型转换不会将 i 转换为 double 吗?
  • 它确实进行了转换,但是当您将 int 1 转换为 double 时,它​​们没有相同的大小或内存布局,因此它为您提供 0,因为作为 double 它为您提供了 0 的指数(请参阅维基百科页面链接),当你增加它时,你会得到一个 1(以双精度表示,在 64 位上),当你将它作为整数打印回来时,这些位会丢失。
【解决方案2】:

主要原因,printf 语句应该是 -

printf( "%p,%f", p, *p );

这将显示你的双倍增量。

另外 - 如前所述,一个 int 通常是 4 个字节,而一个 double 使用 8 个字节。 (在大多数系统上)

【讨论】:

  • 对于%p 参数应该是(void*)
【解决方案3】:

因为未定义的行为。整数不是浮点数,浮点数也不是整数。除此之外,我想你会发现sizeof(int) != sizeof(double)

你也破坏了strict aliasing rule


与你的问题无关,如果你想打印指针,你应该使用"%p"格式。

【讨论】:

  • incme((double *)&i)中的类型转换;将 int 转换为 double 吗?
  • @user1998844 不,它会将指向int 的指针转换为指向double 的指针。整数值和浮点值在计算机中的编码方式不同,整数以二进制形式存储,而浮点值通常使用IEEE754 编码。
  • @user1998844 除此之外,由于大小差异以及取决于机器endianness,您可能会在函数中写入未分配的内存。
猜你喜欢
  • 1970-01-01
  • 2022-10-14
  • 2020-07-24
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多