- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在GLib文档中,有一章是关于类型转换宏的。在关于将 int
转换为 void*
指针的讨论中,它说(强调我的):
Naively, you might try this, but it's incorrect:
gpointer p;
int i;
p = (void*) 42;
i = (int) p;Again, that example was not correct, don't copy it. The problem is that on some systems you need to do this:
gpointer p;
int i;
p = (void*) (long) 42;
i = (int) (long) p;
(来源:GLib 2.39.92 的 GLib 引用手册,第 Type Conversion Macros 章)。
为什么必须强制转换为 long
?
作为指针转换的一部分,int
的任何必需的扩展是否应该自动发生?
最佳答案
glib 文档是错误的,无论是对于他们(自由选择的)示例还是一般情况。
gpointer p;
int i;
p = (void*) 42;
i = (int) p;
和
gpointer p;
int i;
p = (void*) (long) 42;
i = (int) (long) p;
都将导致相同的值 i
和 p
在所有符合标准的 C 实现上。
该示例选择不当,因为 42
保证由 int
表示和 long
(C11 标准草案 n157:5.2.4.2.1 整数类型的大小)。
一个更具说明性(和可测试性)的例子是
int f(int x)
{
void *p = (void*) x;
int r = (int)p;
return r;
}
这将往返 int
-值 iff void*
可以表示 int
的每一个值可以,这实际上意味着sizeof(int) <= sizeof(void*)
(理论上:填充位,yadda,yadda,实际上并不重要)。对于其他整数类型,同样的问题,同样的实际规则(sizeof(integer_type) <= sizeof(void*)
)。
相反,真正的问题,适当说明:
void *p(void *x)
{
char c = (char)x;
void *r = (void*)c;
return r;
}
哇,那不可能能行,对吧? (实际上,它可能)。为了往返一个指针(软件已经不必要地做了很长时间),你还必须确保你往返的整数类型可以明确表示指针类型的每个可能值。
从历史上看,许多软件都是由猴子编写的,它们假设指针可以通过 int
往返,可能是因为 K&R c 的隐式 int
-“功能”和很多人忘记了#include <stdlib.h>
然后转换 malloc()
的结果到一个指针类型,因此不小心通过int
往返.在机器上,代码是为 sizeof(int) == sizeof(void*)
开发的,所以这有效。当切换到具有 64 位地址(指针)的 64 位机器时,许多软件期望两个相互排斥的事情:
1) int
是一个 32 位 2 的补码整数(通常还期望有符号溢出环绕)
2) sizeof(int) == sizeof(void*)
一些系统(咳咳 Windows 咳咳)也假设sizeof(long) == sizeof(int)
, 大多数其他人有 64 位 long
.
因此,在大多数系统上,将往返中间整数类型更改为 long
修复了(不必要地损坏的)代码:
void *p(void *x)
{
long l = (long)x;
void *r = (void*)l;
return r;
}
除了当然,在 Windows 上。从好的方面来说,对于大多数非 Windows(和非 16 位)系统 sizeof(long) == sizeof(void*)
是真的,所以往返工作双向。
所以:
当然,c 标准在intptr_t
中有一个(自然符合标准的)解决方案|/uintptr_t
(C11 标准草案 n1570:7.20.1.4 能够保存对象指针的整数类型)指定以保证
指针 -> 整型 -> 指针
往返(虽然不是相反)。
关于将 int 转换为指针 - 为什么要先转换为 long? (如 p = (void*) 42; ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25381610/
几个月前,我做了一个功能,我的应用程序正在等待用户文档并做出相应的响应。直到我对项目进行优化并将其更新到最新版本之前,它一直是一种魅力。 如果存在用户文档,则流将产生该文档并关闭该流。 如果云Fire
Stack Overflow 有几个 examples其中函数首先获得可升级锁,然后通过升级获得独占访问。我的理解是,如果不小心使用,这可能会导致死锁,因为两个线程可能都获得了可升级/共享锁,然后都尝
这个问题在这里已经有了答案: MVC 4 Code First ForeignKeyAttribute on property ... on type ... is not valid (1 个回答
以下是部分代码。我需要在 finally 子句中关闭资源。我需要先调用 closeEntry() 还是 close()?我收到一些错误消息。 Error closing the zipoutjava.
我想使用 RxJS-DOM 观察 mousewheel 事件,这样当第一个事件触发时,我转发它然后删除所有值,直到后续值之间的延迟超过先前指定的持续时间。 我想象的运算符可能看起来像: Rx.DOM.
版本似乎与安装的不同。 我在 npm install 上收到警告 我将二进制文件安装到我的家庭/开发目录中,但它不适用于 sudo。所以我安装了apt。 (注意:我并没有真正安装,我提取并将路径放在/
我正在尝试展示 GAN 网络在某些指定时期的结果。打印当前结果的功能以前与 TF 一起使用。我需要换成 pytorch。 def show_result(G_net, z_, num_epoch, s
我是一名优秀的程序员,十分优秀!