在64位拱上投射指向整数问题警告的指针

我正在编写一个使用导出符号open_exec的linux内核模块

 struct file *open_exec(const char *name) 

它返回一个指针,我可以检查IS_ERR宏的错误:

 if (IS_ERR(file)) return file; 

在编译期间,我收到此警告:

 warning: return makes integer from pointer without a cast 

这是因为我的函数返回一个整数。 如果我尝试施放它:

 return (int) file; 

我没有在我的32位机器上收到警告,但我在我的64位机器上发出警告:

 warning: cast from pointer to integer of different size 

这是因为int和指针的sizeof在32位上是相同的,但它们在64位机器上是不同的。

无论是否投射,代码似乎都有效。 我只是想摆脱警告。

如何正确地转换指向整数的指针并获得我期望的值,同时没有得到编译器警告? 我期望的值本质上是linux内核代码库的include/asm-generic/errno-base.h中列出的整数。

由于我只是在IS_ERR()为真的情况下将指针看作是一个整数,我可以肯定它实际上只保存一个整数值。

linux/err.hPTR_ERR()宏也是定义IS_ERR()地方, IS_ERR()一个真正是错误代码的指针转换为适当的类型( long )。

你应该使用类似的东西:

 if (IS_ERR(file)) return PTR_ERR(file); 

在源代码中搜索PTR_ERR()现有用法,你会发现这是一种常见的模式。

您的函数可能适合返回long而不是int – 但所有错误代码都应该在int表示。

您无法正确地将指针强制转换为较小尺寸的句点。 如果你确定存储了什么指针,你可以做一些转换。

例如,如果您知道指针仅设置了最低32位,则可以将其强制转换并使用某些特定于编译器的编译指示来抑制警告。 或者,如果您希望散列指针以便在哈希表之类的内容中使用,则可以使用较低的32位对高32位进行排序。

如果不了解以后如何使用该int则无法确定这一点。

我不知道你有时想从errno-base.h返回一个数字,有时候还有一个指针 – 接收函数如何能够将两者分开? 那是相同的,那么在Linux GCC上,

  • int是32位宽,无论你是32位还是64位linux
  • 指针在64位体系结构上是64位宽,在32位体系结构上是32位宽
  • 32位架构上的32位宽,64位架构上的64位宽。
  • long long总是64bit宽

因此在64位体系结构上投射指向int的指针意味着你将64位值设置为32位值,并且你可以确定你将丢失指针中的部分64位信息 – 这就是编译器正如你自己指出的那样,警告就是全部。

如果你想从指针转换为“匿名”的东西,那么你的选择应该是longlong longlong long void* – 而void*是最便携的。

另一种方法是将其记录为偏移量,即如果你有一个大的内存区域,你想要“转换”为32位整数,那么将它转换成类似的东西;

  static struct mybigbuffer *globalbuffer; int cast2int(void*x) { return (int)(globalbuffer-(struct mybigbuffer*)x); } 

然而只有知道你的记忆永远不会超过2 ^ 31的globalbuf记录并确保你的指针在边界上保持一致等 – 这是唯一的工作 – 所以除非你100%确定你知道你在做什么,我也不建议这样做 – 坚持使用long或void *作为安全选项。