llvm中数组和指针类型的区别
Difference between array and pointer types in llvm
例如,如果我有以下结构
%struct.foo_struct = type { [3 x i32], i16*, i32}
假设我们有一个指针%struct.foo_struct* %P
。
我知道我可以 %tmp0 = getelementptr inbounds %struct.foo_struct, %struct.foo_struct* %P, i64 0, i32 0, i64 2
来获取结构的 i32 数组中的第三个元素(结构中的第一个元素),但是我可以 %tmp1 = getelementptr inbounds %struct.foo_struct, %struct.foo_struct* %P, i64 0, i32 1, i64 2
来获取第三个元素吗在结构的 i16 数组中(结构中的第二个元素),假设 i16 数组至少有第三个元素?
我没有在网上找到任何讨论这两种类型之间区别的帖子,所以我可以假设它们是相同的吗?
不可以,因为数组的第二个元素没有三个条目。刚好有一个。
指针类型是指向某物的指针;它的实例占用的内存与指针一样多。一个数组是 n 个东西;一个实例占用的内存是那个东西的n倍。
假设使用零填充的 32 位平台:
如果要进行位转换以将 i16* 视为数组并写入第三个或第四个条目,则会覆盖 i32,因为 i16* 占用的内存与指针一样多。在 32 位平台上,两个条目的 i16 数组与指针一样大,因此第三个和第四个条目将与 i32 重叠,并且写入第五个条目或稍后写入超出结构的末尾。
你不能。原因很简单,GEP 指令 从不取消引用指针 。
在
%tmp1 = getelementptr inbounds %struct.foo_struct, %struct.foo_struct* %P, i64 0, i32 1, i64 2
i32 1
指的是i16*
指针,我们可以称之为ptr
。现在 i64 2
将引用 *(ptr + 2)
,这是非法的,因为它有效地试图取消引用 ptr
,而 GEP 不喜欢这样做。
如果结构的第一个元素是 [3 x i32]*
类型,您也会遇到同样的麻烦。请参阅 https://godbolt.org/z/ch9hGs 并注意作为指针的结构成员如何始终需要加载指令。
此外,如果你有一个 i32*
指针和一个 [n x i32]
数组,唯一真正的区别是你总是可以分辨出后者的大小,而不是前者。
例如,如果我有以下结构
%struct.foo_struct = type { [3 x i32], i16*, i32}
假设我们有一个指针%struct.foo_struct* %P
。
我知道我可以 %tmp0 = getelementptr inbounds %struct.foo_struct, %struct.foo_struct* %P, i64 0, i32 0, i64 2
来获取结构的 i32 数组中的第三个元素(结构中的第一个元素),但是我可以 %tmp1 = getelementptr inbounds %struct.foo_struct, %struct.foo_struct* %P, i64 0, i32 1, i64 2
来获取第三个元素吗在结构的 i16 数组中(结构中的第二个元素),假设 i16 数组至少有第三个元素?
我没有在网上找到任何讨论这两种类型之间区别的帖子,所以我可以假设它们是相同的吗?
不可以,因为数组的第二个元素没有三个条目。刚好有一个。
指针类型是指向某物的指针;它的实例占用的内存与指针一样多。一个数组是 n 个东西;一个实例占用的内存是那个东西的n倍。
假设使用零填充的 32 位平台:
如果要进行位转换以将 i16* 视为数组并写入第三个或第四个条目,则会覆盖 i32,因为 i16* 占用的内存与指针一样多。在 32 位平台上,两个条目的 i16 数组与指针一样大,因此第三个和第四个条目将与 i32 重叠,并且写入第五个条目或稍后写入超出结构的末尾。
你不能。原因很简单,GEP 指令 从不取消引用指针 。
在
%tmp1 = getelementptr inbounds %struct.foo_struct, %struct.foo_struct* %P, i64 0, i32 1, i64 2
i32 1
指的是i16*
指针,我们可以称之为ptr
。现在 i64 2
将引用 *(ptr + 2)
,这是非法的,因为它有效地试图取消引用 ptr
,而 GEP 不喜欢这样做。
如果结构的第一个元素是 [3 x i32]*
类型,您也会遇到同样的麻烦。请参阅 https://godbolt.org/z/ch9hGs 并注意作为指针的结构成员如何始终需要加载指令。
此外,如果你有一个 i32*
指针和一个 [n x i32]
数组,唯一真正的区别是你总是可以分辨出后者的大小,而不是前者。