Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 传递重新解释\u将指针强制转换为void*_C++_Function_C++11_Pointers_Void - Fatal编程技术网

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 );