我有整数值,用于访问不相关数据存储中的数据,即句柄。我已选择将整数包装在结构中以便具有强类型对象,以便不能混合不同的整数。他们是,而且必须是POD。这就是我正在使用的:
struct Mesh {
int handle;
};
struct Texture {
int handle;
};
我有这些句柄的数组,例如:Texture* textureHandles;
。
有时我需要将句柄数组作为int*
传递给代码的更通用部分。现在我正在使用:
int* handles = &textureHandles->handle;
它本质上是一个指向struct的第一个元素的指针,并将其解释为一个数组。
我的问题基本上是这是合法的,还是违反了严格别名来操纵指向同一内存的int* handles
和Texture* textureHandles
。我认为这应该被允许,因为在两种情况下都以相同的方式访问基础类型(int
)。我的保留与以下事实有关:我通过在一个结构中获取成员的地址来访问多个结构。
作为我的第一个问题的延伸,以下是否可以?
int* handles = reinterpret_cast<int*>(textureHandles);
答案 0 :(得分:10)
reinterpret_cast<int*>(textureHandles)
绝对和&textureHandles->handle
一样好。标准中有一个特殊的例外,继承自C even,它表示指向适当转换的标准布局结构的指针指向该结构的初始成员,反之亦然。
使用它来修改句柄也没关系。它没有违反别名规则,因为您使用类型为int
的左值来修改int
类型的子对象。
增加结果指针,并使用它来访问Texture
个对象数组中的其他元素,但有点不确定。 Jerry Coffin已经指出sizeof(Texture) > sizeof(int)
有可能。但是,即使sizeof(Texture) == sizeof(int)
,指针算法仅针对指向数组的指针定义(其中任意对象可以被视为长度为1的数组)。你在任何地方都没有int
的数组,因此添加内容是未定义的。
答案 1 :(得分:5)
不,这不能保证有效。特别是,允许编译器在结构的任何元素之后插入填充,但不允许在数组的元素之间插入填充。
那就是说,只有一个元素(类型int
的结构,或者至少那么大的结构,例如long
),大多数编译器赢得的机会都很大。插入任何填充,因此您当前的使用情况通常相当安全。
答案 2 :(得分:1)
它肯定违反了严格的别名,如果该功能可以访问
您可以通过int*
和Mesh*
或Texture*
来排列数组
很好地遇到了问题(虽然可能只有它修改了
以某种方式排列。)
根据您对问题的描述,我不会考虑规则
严格的别名确实是你所关心的。真正的问题
是编译器是否可以添加填充到不是的结构
出现在int
中,以便sizeof( Mesh ) > sizeof( int )
。和
虽然答案是正式肯定的,我无法想象一个编译器
这样做,至少在今天,至少在int
或更大的类型中
struct
。 (一个单词寻址的机器可能会添加填充到一个
仅包含struct
的{{1}}。)
真正的问题可能更多的是通用代码是否 遗产,不能改变或不改变。否则,明显的解决方案 是创建一个通用句柄类型:
char
然后从中派生您的类型,或使用struct Handle
{
int handle;
};
如你所愿。有(或至少是)允许的保证
通过指向其他人的指针访问reinterpret_cast
的成员
struct,只要成员和所有前面的成员都相同。
这就是你如何模拟C中的继承。即使是保证
已被删除 - 这是它在C ++中出现的唯一原因
是出于C兼容性的原因 - 没有编译器敢于违反
它,考虑到依赖它的现有软件的数量。 (该
例如,Python的实现。几乎所有的Python
插件,包括用C ++编写的插件。)