[英]Iterate through a struct with a pointer
我目前有这个代码:
struct LAYOUT {
WORD a [8] = {::Rook, ::Knight, ::Bishop, ::Queen, ::King, ::Bishop, ::Knight, ::Rook};
WORD b [8] = {::Pawn};
WORD empty [32] = {::None};
WORD c [8] = {::Pawn+0x6};
WORD d [8] = {::Rook+0x6, ::Knight+0x6, ::Bishop+0x6, ::Queen+0x6, ::King+0x6, ::Bishop+0x6, ::Knight+0x6, ::Rook+0x6};
}chessLayout;
LAYOUT* chessboard = &chessLayout;
::Rook
等全局enum
字段表示一个单词,例如: 0x2656
。
我这里的目标是枚举这个结构中的所有元素,所以我写了这段代码:
for(int i = 0; sizeof(LAYOUT) / 2;i++){
printf("%x", *(reinterpret_cast<WORD*>(chessboard+i)));
}
然而,这将返回第一个值,但随后返回不相关的垃圾值,而不是结构中的元素。
有任何想法吗?
提前致谢
在声明中
LAYOUT* chessboard = &chessLayout;
/* ... */
for(int i = 0; sizeof(LAYOUT) / 2;i++){
printf("%x", *(reinterpret_cast<WORD*>(chessboard+i)));
}
指针chessboard
递增,其类型为LAYOUT*
。 这将使指针沿“i * sizeof(LAYOUT)”字节移动,而您想要的是移动到下一个 WORD。
因此,表达式应该看起来像这样(我在演员表之外):
for(int i = 0; i < sizeof(LAYOUT) / 2; ++i){
printf("%x", *(reinterpret_cast<WORD*>(chessboard)+i));
}
编辑:正如@Jarod42 指出的那样,您可能会很快遇到 UB,因为我们正在迭代数组 a 的“结束迭代器”。
确切的解释有时不清楚,并在 SO 和其他地方引起了许多讨论。
这是一个关于此的线程并使用 C++17 offsetof
功能在这种情况下应该有所帮助: 在标准布局 object(例如,使用 offsetof)中进行指针运算时,我们是否需要使用 std::launder?
我相信对此的详细讨论很重要,但有足够的活跃线程,因此在此不再赘述。
为了避免使用 UB 刺激探戈,我会以相反的方式执行此操作,让布局包含整个数据的数组,而a,b,c,d
将是吸气剂。 即使像下面的代码中那样强制转换指针也会是边缘行走,但是我们可以遍历数据,而不用担心它可能会被填充词打断。
using WORD = unsigned short;
namespace LayoutNS {
struct Layout {
WORD data[64];
template <size_t N>
using line = WORD [N];
template <size_t N>
line<N>* operator[] ( line<N>* (*f)(Layout&) )
{
return (*f)(*this);
}
};
}
using LAYOUT = LayoutNS::Layout;
// better to avoid such cast either, can we go just with a pointer? Or return a copy?
LAYOUT::line<8>* line_a (LAYOUT& l) { return (LAYOUT::line<8>*)(l.data); }
LAYOUT::line<8>* line_b (LAYOUT& l) { return (LAYOUT::line<8>*)(l.data+8); }
LAYOUT::line<32>* empty (LAYOUT& l) { return (LAYOUT::line<32>*)(l.data+16); }
LAYOUT::line<8>* line_c (LAYOUT& l) { return (LAYOUT::line<8>*)(l.data+48); }
LAYOUT::line<8>* line_d (LAYOUT& l) { return (LAYOUT::line<8>*)(l.data+56); }
int main()
{
LAYOUT test = {};
auto test_a = test[line_a];
std::cout << (*test_a)[1];
}
避免间接级别和 C++11 功能的简化版本:
struct LAYOUT {
WORD data[64];
WORD* operator[] ( WORD* (*f)(LAYOUT&) )
{
return (*f)(*this);
}
};
WORD* line_a (LAYOUT& l) { return (l.data); }
WORD* line_b (LAYOUT& l) { return (l.data+8); }
WORD* empty (LAYOUT& l) { return (l.data+16); }
WORD* line_c (LAYOUT& l) { return (l.data+48); }
WORD* line_d (LAYOUT& l) { return(l.data+56); }
int main()
{
LAYOUT test = {{1,3,4,5}};
auto test_a = test[line_a];
std::cout << test_a[1];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.