从 size_t 或 uintptr_t 来回转换指针会破坏严格的别名吗?

Does casting a pointer back and forth from size_t or uintptr_t break strict aliasing?

我提议更改 public API 目前看起来像这样的图书馆:

typedef size_t enh;  /* handle */

int en_open(enh *handle)
{
    struct internal *e = malloc(...);
    *handle = (enh)e;
    return 0;
}

int en_start(enh handle)
{
    struct internal *e = (struct internal*)handle;
    return do_something(e);
}

这种来回转换到 size_t 的用法是否会破坏严格的别名?

郑重声明,我建议在 public API 中对 struct internal 进行典型的不透明前向声明,如 this Programmers.SE question about the same code 所示。

别名是关于两个不同类型的指针被用来访问相同的字节。在您的代码中情况并非如此。当您访问句柄后面的数据成员时,您总是通过 struct internal* 类型的指针来完成。所以这里没有伤害。

您的代码中唯一有问题的是,您正在使用 size_t 传递指针。 Afaik,该标准不保证您可以安全地将指针转换为 size_t 并返回,即使任何理智的实现都允许这样做。正确的整数类型选择是 uintptr_t,但您甚至不需要它:

我认为,您应该在界面中使用不透明指针。即,只需声明

typedef struct internal internal;

进入你的publicheader并保留相应的

struct internal {
    ...
}

private(当然,用合理的 public 名称替换 internal)。 public 函数可以简单地声明为:

int en_open(internal** outHandle);
int en_close(internal* handle);

这样,您就可以在客户端代码中进行完美的类型检查,并且无需进行任何类型转换。