从 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);
这样,您就可以在客户端代码中进行完美的类型检查,并且无需进行任何类型转换。
我提议更改 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);
这样,您就可以在客户端代码中进行完美的类型检查,并且无需进行任何类型转换。