【问题标题】:Passing pointer of unsigned int to pointer of long int将 unsigned int 的指针传递给 long int 的指针
【发布时间】:2015-06-23 21:45:28
【问题描述】:

我有一个示例代码在 32 位系统中可以正常工作,但是当我为 64 位系统交叉编译它并尝试在 64 位机器上运行时,它的行为有所不同。

谁能告诉我为什么会这样?

#include <usr/include/time.h>
#include <sys/time.h>

void func(time_t * inputArg)
{
   printf("%ld\n",*inputArg);
}
int main()
{
   unsigned int input  = 123456;
   func((time_t *)&input);
}

这里的“time_t”是linux系统库头文件中定义的类型,类型为“long int”。 此代码适用于 32 位系统,但不适用于 64 位系统。

对于 64 位,我试过这个:

#include <usr/include/time.h>
#include <sys/time.h>

void func(time_t * inputArg)
{
   printf("%ld\n",*inputArg);
}
int main()
{
   unsigned int input  = 123456;
   time_t tempVar = (time_t)input
   func(&tempVar);
}

这很好用,但我在整个应用程序中多次使用第一种方法。任何替代解决方案将不胜感激。

【问题讨论】:

  • 我认为输入应该是size_t,因为64位平台上的time_t是64位数字,所以你丢失了一半的数据,编译器应该对此给出警告-实际上为什么不直接使用time_t?
  • 如果是时候为什么不直接使用time_t?这将帮助您避免许多未定义的行为

标签: c++ c pointers 64-bit 32bit-64bit


【解决方案1】:

谁能告诉我为什么会这样?

取消引用大小与指向对象类型不同的整数指针具有未定义的行为。

如果指向的整数小于指针指向的类型,您将读取不相关的字节作为取消引用数字的一部分。

您的解决方法有效,因为您传递了一个指向正确类型对象的指针,但考虑到您的输入不能代表 time_t 可以表示的所有值。

最好的解决办法是一开始就使用正确的类型。使用time_t 作为输入。

【讨论】:

  • 在指针类型之间转换为相同整数类型的有符号/无符号版本(可能发生在 32 位系统上)然后访问指向的对象不是未定义的。强制转换显然是可能的,并且根据标准的 3.10/10 第 4 项允许使用别名,该标准允许通过“一种类型 [即取消引用的别名指针,-ps] 访问对象,该类型是对应于 cv 的有符号或无符号类型-对象的动态类型的限定版本”。做出这些类型假设是不可移植的,这是 types.h 的原因。
  • @PeterSchneider 啊,我现在已经尝试在这方面更正我的答案。
【解决方案2】:

您的“固定”代码有一个强制转换,可以让编译器将您的unsigned int 值转换为time_t。您的原始代码假定它们是相同的。

在您的 32 位系统上,它们是相同的,所以您很幸运。在您的 64 位系统上,您会发现调用未定义行为时会发生什么。

换句话说,C 和 C++ 都允许您将指针转换为您想要的任何内容,但您需要确保此类转换是安全的。

【讨论】:

  • 如果你的意思是第二个用“固定代码”剪断,即time_t tempVar = (time_t)input,演员不会做任何事情。这是标准转换之一的显式表示法,即整数提升(假设 time_t 是整数)。它可以简单地省略,没有任何语义或生成的代码差异(因为 time_t 至少与 int 一样大)。
  • AFAIK 不能保证 time_tint 一样大,甚至不能保证它 int。虽然在实践中基本上是这样。不过,关键是有一个地方可以进行转换。虽然严格来说,即使是这种转换,无论是否显式,都是未定义的行为。
  • 看起来 time_t 可以是浮点类型(参见pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/…)。但无论 size_t 的大小或算术类型如何,从任何整数类型到 size_t 的转换几乎总是实现定义(与 UB 相对)。唯一的 UB 情况是,如果 unsigned int input 的值在浮点类型中“超出可表示的值范围”,这对于 unsigned intsome float 的大多数组合可能是错误的。顺便说一句,UB 可能出现在 printf... 最安全的转换为 double 以进行打印。
  • 亚当亚...我很幸运..!!谢谢。
  • @PeterSchneider 问题是关于time_t,而不是size_t。虽然你的观点对两者都有效。
【解决方案3】:

感谢您的回复。 其实我在 32 位机器和 64 位机器上打印 sizeof 'long int' 时发现了我的错误。

32位机: sizeof(int) = 32bit & sizeof(long int) = 32 bit & sizeof(long long int) = 64 bit
64位机器: sizeof(int) = 32bit & sizeof(long int) = 64 bit & sizeof(long long int) = 64 bit

【讨论】:

  • long int 有什么关系?比较inttime_t
  • time_t 内部类型转换为“long int”。
  • 在那个特定平台上可能是这样,但语言没有这样的保证。由于您的问题归结为平台差异,我不明白您为什么坚持做出更多依赖于平台的假设。
猜你喜欢
  • 2013-12-06
  • 2017-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
相关资源
最近更新 更多