C++ 传递重新解释\u将指针强制转换为void*
在下面- 意思是将C++ 传递重新解释\u将指针强制转换为void*,c++,function,c++11,pointers,void,C++,Function,C++11,Pointers,Void,在下面- 意思是将reinterpret\u casted指针传递到此函数和原始S1结构的大小,或者我必须再次reinterpret\u cast将其返回S1,然后再次传递指针 不必再次将转换重新解释为原始类型将为类似类型(如S1)节省一些开关箱。请注意,someFunc可以根据传入的size轻松找到类型,因为这些相似类型的大小差别很大。是 someFunc(ptr, sizeof(obj1)); 很好。。。但这仅仅是因为obj1实际上是类型S1。我有点怀疑你的评论“给我留一些类似S
reinterpret\u cast
ed指针传递到此函数和原始S1
结构的大小,或者我必须再次reinterpret\u cast
将其返回S1
,然后再次传递指针
不必再次将转换重新解释为原始类型将为类似类型(如S1
)节省一些开关箱。请注意,someFunc
可以根据传入的size
轻松找到类型,因为这些相似类型的大小差别很大。是
someFunc(ptr, sizeof(obj1));
很好。。。但这仅仅是因为obj1实际上是类型S1
。我有点怀疑你的评论“给我留一些类似S1类型的开关盒”
我将值赋给结构S1的成员,然后在其他地方使用它们作为结构S指针,方法是重新解释将原始S1转换为S。这很好
现在稍微向前一点,我有一个函数someFunc(constvoid*ptr,int len),它接受一个constvoid*指针和要传递的结构的长度
那么我可以这样做吗?
你可以。你永远不应该这样
您在代码中应该有这样一个API的唯一原因是,如果您没有编写它,但必须使用它,没有权利接触它所在的代码,和/或没有时间预算来包装或重写它(这应该需要一个小时左右)
使用继承的替代代码(避免重新解释_cast和整个问题):
someFunc:
auto someFunc(S& sref);
S s{1, 2};
S1 s1{1, 2, 3, 4};
someFunc(s); // works
someFuncf(s1); // also works
不必再次将_cast重新解释为原始类型将为类似类型(如S1)节省一些切换案例
必须在用户类型(您的结构)上键入reinterpret_cast,这表明您尚未将常见行为提取到常见基类/结构中。结构的地址是结构的第一个字节的地址。即使我在标准中找不到任何引用,它也是C++中的一个常见习惯用法(如C中),它将指针指向一个POD结构(或多或少的C结构),指向一个指向该类的初始子序列的指针。当转换为
void*
时,两者将给出相同的值
所以用你的符号:
someFunc(ptr, sizeof(obj1));
及
都是一模一样的电话
我将值赋给结构S1的成员,然后在其他地方使用它们作为结构S指针,方法是重新解释将原始S1转换为S。这很好
这是未定义的行为。一个可能的症状是它“工作正常”
S1
和S
是布局兼容的,但它们不是同一个对象。一个S1
或一个S
存在于该位置,而不是两者都存在
访问实际上不存在的对象存在未定义的行为
您需要的是指针不可逆性
这是合法的C和C++:
struct S{
int a; int b;
};
struct S1{
S s;
int c; int d;
};
现在,指向S1
的指针可以重新解释为指向S
的指针,a
和b
与原始S1
中的S.a
和S.b
相同
在C++中,这也可以继承:
struct S1:S {
int c; int d;
};
在这两种情况下,都有一个S1
和一个S
对象,因此您永远不会访问不存在的对象
你所做的往往会奏效;但是在C++标准下,它是未定义的行为。 作为一个实际问题,优化器可以假设它永远不会发生,对
S
的任何访问都不会修改S1
的状态,反之亦然,这可能会在程序中导致异常意外的行为。当您将程序升级到链接时间优化时,新的极其危险的行为可能会自动出现
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
s1obj1{1,2,3,4};
静态铸件(&obj1)。a=99;
std::cout@LogicStuff是的,我这次把它标为粗体。@hg\u git你为什么在这里使用reinterpret\u cast
?@TheApache因为S1
和S
是两种不同的类型。听起来像是XY问题。你到底想在这里实现什么?@NathanOliver我有类似的标准布局类型S1
,S2
,S3
,S4
,具有与类型S
匹配的公共初始序列。对于某些库,它们都需要转换为类型S
指针。然后我需要将它们传递到另一个函数中,该函数接受const void*
和原始类型的长度。因此,将浇铸到S
的指针和原始类型的长度S1
或S2
传递是否安全。。不管是哪一个。这里-因为还有一些其他类型,如S1
-S2
,S3
,S4
,它们的成员比S1
多,但也与S
匹配。因此,当我以这种方式创建指向其中一个函数的指针时,我不必将其回传给someFunc
。但是如果我需要回溯,我必须在它们的长度上放置一个开关盒,并回溯到原始类型的新指针,然后传递它们。这里-。类似类型的S1
,S2
。。不会彼此交互,只转换为S
,正确使用,然后以其原始长度传递给函数。这安全吗?很好。你对每个ptr都使用了正确的长度如果可以的话我会继承的,但是这是一个C库,所以在使用它的地方不允许这样的特性。然后考虑包装:在隐藏C++的C结构中添加一层C++类,只在代码中公开这些类。C库我特别提到没有严格的别名违反,它们已经处理了。我无法重新定义结构,因为它们仅由它们提供。我只能构造和传递它们。@上面的C++代码在上面的库中有严格的混叠违反。您正在使用的C库并不重要,它不能神奇地生成未定义的beh
someFunc(obj1, sizeof(obj1));
struct S{
int a; int b;
};
struct S1{
S s;
int c; int d;
};
struct S1:S {
int c; int d;
};
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
S1 obj1 { 1,2,3,4 };
auto* s = reinterpret_cast<S*>(&obj1);
void* ptr = s;
Assert( static_cast<S1*>(ptr) == &obj1 );