【问题标题】:casting 8-bit pointer to long将 8 位指针转换为 long
【发布时间】:2017-08-28 04:18:39
【问题描述】:

我正在尝试在我的 c++ 项目中使用第 3 方 c 库,我在 64 位 Windows 上使用 Visual Studio 开发该库。 32位和64位都编译成功;但是,在 64 位运行时,我在外部库中发现了一个问题,因为它执行以下操作:

double* foo(){
     double* b; long a; long i;
     /*
       ... do some stuff to assign values to b, a, i ...
     */
     return ( (long)b + a + i );
}

问题是(至少在 Windows 上) double* 在 x86 架构中由 4 个字节表示,在 x64 中由 8 个字节表示,因此在 return 语句中强制转换 b 是错误的。

我的问题是,有没有办法可以从指针b 的 8 位表示中“提取”其 4 字节地址,从而保持表达式 (b+a) 有意义?

谢谢

【问题讨论】:

  • 请了解位和字节的区别,这对于有效交流思想至关重要。指针是四个或八个字节,而不是位。
  • 我可能会错过一些明显的东西,但是从返回行中简单地删除(长)不能解决问题吗?
  • 有问题的代码是零意义的。目前尚不清楚它的设计目的是什么,因此很难说什么是适当的修复。如果是你的代码,我的建议是避免任何和所有的演员表。
  • @n.m.我认为铸造是为了使加法表现得好像 a 和 i 是以字节为单位的数量,而不是双倍。问题可能是因为 Windows 64 上的 long 可能只有 32 位,所以指针会被截断。
  • 如果这是第三方库代码,我会把它扔掉,或者至少 非常 重新编译它,最高警告级别,所有警告都被视为错误,然后手动分析每个警告并思考如何消除它。

标签: c pointers 32bit-64bit


【解决方案1】:

大概是为了避免在sizeof(double)的倍数上进行指针算术运算。

您可以对char * 指针执行相同的操作,完全避免大小问题。我还添加了转换回原始指针类型的代码,其中缺少代码。

return (double *)( (char *)b + a + i );

注意:您应该知道,您可以轻松创建未对齐的指针,如果取消引用,可能会导致未定义的行为。这也是您原始代码的问题。

小心;你的代码看起来很可疑,它可能还有其他潜在的地雷。

【讨论】:

  • 大奖!将 (long) 更改为 (char*) 就可以了。现在 x64 版本的行为与其 x86 版本完全相同。
  • @gcaglion 很高兴它成功了。但就像我说的那样,指针算术让我有点紧张。出于好奇,你能透露一下图书馆是什么吗?
  • 我自己从不使用指针算法,但是,正如我所写,我决定使用现有的 3rd 方外部库来节省一些时间,而且我确实这样做了。顺便说一下,外部代码来自svmlight.joachims.org(具体是svm_learn.c中的函数kernel_cache_clean_and_malloc()
  • @gcaglion 最后一次更新是在 2008 年,当时恐龙还在地球上漫游。该站点看起来像是直接从 1998 年开始的。但是出于好奇,我下载了该库,但在其中找不到这样的代码。肯定有很多虚假和可疑的演员表。
  • @n.m.可能是第 3711 行的代码。有趣的是,整数转换似乎毫无意义:有 sizeof(CFLOAT) 用于手动乘以指针增量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
相关资源
最近更新 更多