Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为您的C++;库和严格别名 提供C API时的一种常见模式是在公共头中向前声明一些不透明类型,这些类型被传递到API方法,然后将代码> RealTytPask< /Cord>它们一次插入到您的定义的C++类型中,一旦在翻译单元内部(因此回到C++的地盘)。 以LLVM为例:_C++_C_Llvm_Strict Aliasing - Fatal编程技术网

为您的C++;库和严格别名 提供C API时的一种常见模式是在公共头中向前声明一些不透明类型,这些类型被传递到API方法,然后将代码> RealTytPask< /Cord>它们一次插入到您的定义的C++类型中,一旦在翻译单元内部(因此回到C++的地盘)。 以LLVM为例:

为您的C++;库和严格别名 提供C API时的一种常见模式是在公共头中向前声明一些不透明类型,这些类型被传递到API方法,然后将代码> RealTytPask< /Cord>它们一次插入到您的定义的C++类型中,一旦在翻译单元内部(因此回到C++的地盘)。 以LLVM为例:,c++,c,llvm,strict-aliasing,C++,C,Llvm,Strict Aliasing,在本示例中,声明了typedef: typedef struct LLVMOpaqueContext *LLVMContextRef; LLVMContextRef LLVMContextCreate(void); LLVMOpaqueContext未在项目中的任何其他位置引用 在以下方法中声明: typedef struct LLVMOpaqueContext *LLVMContextRef; LLVMContextRef LLVMContextCreate(void); 定义如下:

在本示例中,声明了typedef:

typedef struct LLVMOpaqueContext *LLVMContextRef;
LLVMContextRef LLVMContextCreate(void);
LLVMOpaqueContext
未在项目中的任何其他位置引用

在以下方法中声明:

typedef struct LLVMOpaqueContext *LLVMContextRef;
LLVMContextRef LLVMContextCreate(void);
定义如下:

wrap
(和
unwrap
)由以下中的宏定义:

因此,我们看到C API基本上获取一个指向
LLVMOpaqueContext
的指针,并将其强制转换为
llvm::LLVMContext
对象,以执行对其调用的任何方法


我的问题是:这不是违反了严格的别名规则吗?若否,原因为何?如果是这样的话,如何在公共接口边界合法地实现这种类型的抽象?

这不是严格的别名冲突。首先,严格别名是指通过错误类型的glvalue访问对象

在您的问题中,您创建一个
LLVMContext
,然后使用
LLVMContext
左值访问它。那里没有非法的别名

唯一可能出现的问题是指针转换不会返回相同的指针。但这也不是问题,因为
reinterpret\u cast
保证在往返转换中返回相同的指针。只要我们转换的指针类型是适当对齐的数据(即不比原始类型严格)


这是一种好的还是坏的做事方式是有争议的。我个人不会费心处理
LLVMOpaqueContext
并返回
struct LLVMContext*
。它仍然是一个不透明的指针,C头用
struct
声明它,而类型定义用
class
声明它并不重要。这两个是可互换的,直到类型定义的点。

@ MEPOMPON-无效指针值也是C++中的一个东西。但我认为,就UB的原因而言,严格的别名冲突和正在使用的无效地址(就像您在代码片段中使用的地址一样)是有区别的。@ArneVogel-我想Clang之所以选择它,是因为它与MSVC的互操作性。我知道微软的名字也因此受到影响。但是我不认为返回指针的这种受限情况可能会导致问题,因此可以在定义类的TU中关闭警告。不过谢谢你提出来。直到现在我才知道Clang是这样做的。<代码> *P<代码>在C++中没有指向指针的L to to R转换,除非你有一个指向易失性的指针。@ PasSerB:不,即使读取无效的指针值也是UB。(如果您有一个段+偏移量体系结构,并且加载无效的段描述符会导致陷阱,那么仅测试NULL就可能导致崩溃。)@HolyBlackCat:3.9.2 p3 in“指向cv的指针符合条件(3.9.3)或cv void可用于指向未知类型的对象。此类指针应能够容纳任何对象指针。
cv void*
类型的对象应具有与
cv char*
相同的表示和对齐要求(我的重点)。请注意,此豁免仅适用于char*和void*。
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef)