将 reinterpret_cast 指针作为 void * 传递
passing reinterpret_cast pointer as void *
在下面code-
#include <iostream>
using namespace std;
struct S1{
int a; int b; int c; int d;
};
struct S{
int a; int b;
};
int main() {
S1 obj1;
obj1.a = 1;
obj1.b = 2;
obj1.c = 3;
obj1.d = 4;
cout << obj1.a << " "
<< obj1.b << " "
<< obj1.c << " "
<< obj1.d << "\n";
// more code
auto ptr = reinterpret_cast<S *>(&obj1);
cout << ptr->a << " " << ptr->b << "\n";
// more code
// someFunc(ptr, sizeof(obj1));
}
我正在为结构 S1 的成员赋值,然后通过 reinterpret_cast
将原始 S1
转换为 S
,将它们作为结构 S
指针在其他地方使用。这很好用。
现在稍微提前一点,我有一个函数 someFunc(const void *ptr, int len)
,它接受一个 const void *
指针和指向所传递结构的长度。在这种情况下,预计将 S1
结构传递给它,并且在它内部有一些 memcpy
调用来复制结构并处理该副本。 那我可以这样做吗? -
// more code
someFunc(ptr, sizeof(obj1));
}
意思是将 reinterpret_cast
ed 指针传递给这个函数和原始 S1
结构的大小,或者我必须再次 reinterpret_cast
它返回 S1
然后传递再次指针。
不必再次 reinterpret_cast
到原始类型,这将为我节省一些类似类型 S1
的开关盒。注意 someFunc
可以根据传入的 size
轻松找出类型,因为那些相似的类型在大小上有很大差异。
是的,
someFunc(ptr, sizeof(obj1));
没问题……但这只是因为 obj1 实际上是 类型 S1
。我有点怀疑你的评论 "save me some switch cases for similar types like S1".
I'm assigning values to members of structure S1 and then using them somewhere else as struct S pointer by reinterpret_casting the original S1 to S. This works fine.
Now a little ahead, I've a function someFunc(const void *ptr, int len) that takes a const void * pointer and length to the structure being passed.
So can I do this?
可以。你永远不应该。
你的代码中应该有这样一个 API 的唯一原因是,如果你没有编写它但必须使用它,无权触摸它所在的代码,and/or 没有时间预算来包装或重写它(这应该需要一个小时左右)。
替代代码,使用继承(避免 reinterpret_cast 和整个问题):
struct S { int a, b; }; // defines common behavior between structures
// this is what base classes are for
struct S1: S { int c, d; }; // inherit S
一些函数:
auto someFunc(S& sref);
S s{1, 2};
S1 s1{1, 2, 3, 4};
someFunc(s); // works
someFuncf(s1); // also works
Not having to reinterpret_cast again to original type will save me some switch cases for similar types like S1.
必须在用户类型(您的 S 结构)上键入 reinterpret_cast 表明您尚未将常见行为提取到通用基础中 classes/structures。
结构的地址是结构的第一个字节的地址。即使我在标准中找不到任何参考,C++ 中的一个常见习惯用法(就像在 C 中一样)将指向 POD 结构(或多或少是 C 结构)的指针转换为指向初始子序列的指针其中 class。当转换为 void *
时,两者将给出相同的值。
所以用你的符号:
someFunc(ptr, sizeof(obj1));
和
someFunc(obj1, sizeof(obj1));
完全一样的调用。
I'm assigning values to members of structure S1 and then using them somewhere else as struct S pointer by reinterpret_casting the original S1 to S. This works fine.
这是未定义的行为。一种可能的症状是 "works fine".
S1
和 S
是布局兼容的,但它们不是同一个对象。 S1
或 S
居住在该位置,不能同时居住。
访问实际上不存在的对象是未定义的行为。
你想要的是pointer-inconvertibility。
这是合法的 C 和 C++:
struct S{
int a; int b;
};
struct S1{
S s;
int c; int d;
};
现在,指向 S1
的指针可以重新解释为指向 S
的指针,并且 a
和 b
与 [=22] 相同=] 和 s.b
在原来的 S1
.
在 C++ 中,这也可以通过继承来完成:
struct S1:S {
int c; int d;
};
在这两种情况下,那里都有一个 S1
和一个 S
对象,因此您永远不会访问不存在的对象。
你所做的往往会奏效;但在 C++ 标准下它是未定义的行为。
作为一个实际问题,优化器可以假设它永远不会发生,即无法访问 S
可以修改 S1
的状态,反之亦然,这可能会导致您的系统出现极其意外的行为程序。当您将程序升级到 link 时间优化时,可能会自发出现新的极其危险的行为。
S1 obj1 { 1,2,3,4 };
static_cast<S*>(&obj1).a=99;
std::cout << obj1.a; // can legally print out 1, or anything else really
std::cout << obj1.a; // it could now print out 99. Why? Undefined behavior
一旦您拥有实际的指针互换性,C++ 标准就会保证:
S1 obj1 { 1,2,3,4 };
auto* s = reinterpret_cast<S*>(&obj1);
void* ptr = s;
Assert( static_cast<S1*>(ptr) == &obj1 );
Assert
传球。
在下面code-
#include <iostream>
using namespace std;
struct S1{
int a; int b; int c; int d;
};
struct S{
int a; int b;
};
int main() {
S1 obj1;
obj1.a = 1;
obj1.b = 2;
obj1.c = 3;
obj1.d = 4;
cout << obj1.a << " "
<< obj1.b << " "
<< obj1.c << " "
<< obj1.d << "\n";
// more code
auto ptr = reinterpret_cast<S *>(&obj1);
cout << ptr->a << " " << ptr->b << "\n";
// more code
// someFunc(ptr, sizeof(obj1));
}
我正在为结构 S1 的成员赋值,然后通过 reinterpret_cast
将原始 S1
转换为 S
,将它们作为结构 S
指针在其他地方使用。这很好用。
现在稍微提前一点,我有一个函数 someFunc(const void *ptr, int len)
,它接受一个 const void *
指针和指向所传递结构的长度。在这种情况下,预计将 S1
结构传递给它,并且在它内部有一些 memcpy
调用来复制结构并处理该副本。 那我可以这样做吗? -
// more code
someFunc(ptr, sizeof(obj1));
}
意思是将 reinterpret_cast
ed 指针传递给这个函数和原始 S1
结构的大小,或者我必须再次 reinterpret_cast
它返回 S1
然后传递再次指针。
不必再次 reinterpret_cast
到原始类型,这将为我节省一些类似类型 S1
的开关盒。注意 someFunc
可以根据传入的 size
轻松找出类型,因为那些相似的类型在大小上有很大差异。
是的,
someFunc(ptr, sizeof(obj1));
没问题……但这只是因为 obj1 实际上是 类型 S1
。我有点怀疑你的评论 "save me some switch cases for similar types like S1".
I'm assigning values to members of structure S1 and then using them somewhere else as struct S pointer by reinterpret_casting the original S1 to S. This works fine.
Now a little ahead, I've a function someFunc(const void *ptr, int len) that takes a const void * pointer and length to the structure being passed.
So can I do this?
可以。你永远不应该。
你的代码中应该有这样一个 API 的唯一原因是,如果你没有编写它但必须使用它,无权触摸它所在的代码,and/or 没有时间预算来包装或重写它(这应该需要一个小时左右)。
替代代码,使用继承(避免 reinterpret_cast 和整个问题):
struct S { int a, b; }; // defines common behavior between structures
// this is what base classes are for
struct S1: S { int c, d; }; // inherit S
一些函数:
auto someFunc(S& sref);
S s{1, 2};
S1 s1{1, 2, 3, 4};
someFunc(s); // works
someFuncf(s1); // also works
Not having to reinterpret_cast again to original type will save me some switch cases for similar types like S1.
必须在用户类型(您的 S 结构)上键入 reinterpret_cast 表明您尚未将常见行为提取到通用基础中 classes/structures。
结构的地址是结构的第一个字节的地址。即使我在标准中找不到任何参考,C++ 中的一个常见习惯用法(就像在 C 中一样)将指向 POD 结构(或多或少是 C 结构)的指针转换为指向初始子序列的指针其中 class。当转换为 void *
时,两者将给出相同的值。
所以用你的符号:
someFunc(ptr, sizeof(obj1));
和
someFunc(obj1, sizeof(obj1));
完全一样的调用。
I'm assigning values to members of structure S1 and then using them somewhere else as struct S pointer by reinterpret_casting the original S1 to S. This works fine.
这是未定义的行为。一种可能的症状是 "works fine".
S1
和 S
是布局兼容的,但它们不是同一个对象。 S1
或 S
居住在该位置,不能同时居住。
访问实际上不存在的对象是未定义的行为。
你想要的是pointer-inconvertibility。
这是合法的 C 和 C++:
struct S{
int a; int b;
};
struct S1{
S s;
int c; int d;
};
现在,指向 S1
的指针可以重新解释为指向 S
的指针,并且 a
和 b
与 [=22] 相同=] 和 s.b
在原来的 S1
.
在 C++ 中,这也可以通过继承来完成:
struct S1:S {
int c; int d;
};
在这两种情况下,那里都有一个 S1
和一个 S
对象,因此您永远不会访问不存在的对象。
你所做的往往会奏效;但在 C++ 标准下它是未定义的行为。
作为一个实际问题,优化器可以假设它永远不会发生,即无法访问 S
可以修改 S1
的状态,反之亦然,这可能会导致您的系统出现极其意外的行为程序。当您将程序升级到 link 时间优化时,可能会自发出现新的极其危险的行为。
S1 obj1 { 1,2,3,4 };
static_cast<S*>(&obj1).a=99;
std::cout << obj1.a; // can legally print out 1, or anything else really
std::cout << obj1.a; // it could now print out 99. Why? Undefined behavior
一旦您拥有实际的指针互换性,C++ 标准就会保证:
S1 obj1 { 1,2,3,4 };
auto* s = reinterpret_cast<S*>(&obj1);
void* ptr = s;
Assert( static_cast<S1*>(ptr) == &obj1 );
Assert
传球。