我如何将 int** 转换为 void**?
How do I cast int** to void**?
使用以下代码段:
int n = 11;
int* c = &n;
void** v = &c;
我在 visual studio 中收到以下错误:
the value of type int**
cannot be used to initialize an entity of type void **
.
这很好用:
int n = 11;
int* c = &n;
void* v = c;
但是这个代码片段是针对某人库中的一个更大的问题。
将变量转换为 void**
我做错了什么?
完整示例
使用caen digitizer library他们尝试从外围设备收集数据的方式有这个原型:
/******************************************************************************
* X742_DecodeEvent(char *evtPtr, void **Evt)
* Decodes a specified event stored in the acquisition buffer writing data in Evt memory
* Once used the Evt memory MUST be deallocated by the caller!
*
* [IN] EventPtr : pointer to the requested event in the acquisition buffer (MUST BE NULL)
* [OUT] Evt : event structure with the requested event data
* : return 0 = Success;
******************************************************************************/
int32_t X742_DecodeEvent(char *evtPtr, void **Evt);
这是实现:
int32_t X742_DecodeEvent(char *evtPtr, void **Evt) {
CAEN_DGTZ_X742_EVENT_t *Event;
uint32_t *buffer;
char chanMask;
uint32_t j,g,size;
uint32_t *pbuffer;
uint32_t eventSize;
int evtSize,h;
evtSize = *(long *)evtPtr & 0x0FFFFFFF;
chanMask = *(long *)(evtPtr+4) & 0x0000000F;
evtPtr += EVENT_HEADER_SIZE;
buffer = (uint32_t *) evtPtr;
pbuffer = (uint32_t *) evtPtr;
eventSize = (evtSize * 4) - EVENT_HEADER_SIZE;
if (eventSize == 0) return -1;
Event = (CAEN_DGTZ_X742_EVENT_t *) malloc(sizeof(CAEN_DGTZ_X742_EVENT_t));
if (Event == NULL) return -1;
memset( Event, 0, sizeof(CAEN_DGTZ_X742_EVENT_t));
for (g=0; g<X742_MAX_GROUPS; g++) {
if ((chanMask >> g) & 0x1) {
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j]= malloc(X742_FIXED_SIZE * sizeof (float));
if (Event->DataGroup[g].DataChannel[j] == NULL) {
for (h=j-1;h>-1;h++) free(Event->DataGroup[g].DataChannel[h]);
return -1;
}
}
size=V1742UnpackEventGroup(g,pbuffer,&(Event->DataGroup[g]));
pbuffer+=size;
Event->GrPresent[g] = 1;
}
else {
Event->GrPresent[g] = 0;
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j] = NULL;
}
}
}
*Evt = Event;
return 0;
}
我通过以下方式使用它:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL; // Creating my event pointer
//Doing some config of the device
X742_DecodeEvent(evtptr, &Evt); //Decode the event data for me to read (Throws error)
希望这能提供一些背景信息。
What am I doing wrong with casting a variable to void**?
没有将 int**
转换为 void**
的有效方法,因此您的尝试是错误的。
你可以做的是
int n = 11;
void* c = &n;
void** v = &c;
但是没有完整的例子,无法判断是否适用于你的问题。
这就是语言的工作原理。
void *
指针得到特殊处理:指向任意类型的指针可以转换为指向 void
的指针(只要这样做不会从指针)。
void **
得到 none 的特殊待遇。它只是一个普通的指针类型,比如 int **
.
int32_t X742_DecodeEvent(char *evtPtr, void **Evt)
既然你想传递 CAEN_DGTZ_X742_EVENT_t **
给你的函数,你应该相应地改变参数类型:CAEN_DGTZ_X742_EVENT_t **Evt
.
在评论中建议您使用 void ** v = (void**)&c;
。
虽然您可以可能使其在实践中发挥作用,但严格来说,对*v
的任何访问都将违反strict aliasing 并导致未定义的行为。我不会使用那个解决方案。
void**
表示指向 void*
对象的指针。但是该代码中没有 void*
对象指向! void**
并不意味着 "a pointer to any kind of pointer",所以请避免这样使用它。如果您有一个指向可能是 int*
、double*
等的指针,void*
是比 void**
更好的类型。更好的是模板或 std::variant
或 std::any
.
但是如果你必须使用一个使用 void**
的库来表示 "a pointer to a pointer to a type unknown at compile time" 或类似的东西,你可能需要创建一个 void*
指针来使用,或者可能需要添加强制转换来解决编译器不喜欢这种转换的事实(有充分的理由)。问题是,至少有两种合理的方法可以做到这一点! (他们最终会在许多常见的计算机体系结构上做完全相同的事情,但这并不能保证。)
// LibraryFunc1 takes a void** argument that somehow means an int* pointer.
// But which call is correct?
int* data_in = generate_data();
LibraryFunc1(reinterpret_cast<void**>(&data_in)); // ?
void* p1 = data_in;
LibraryFunc1(&p1); // ?
// LibraryFunc2 returns a void** argument that somehow means an int* pointer.
void** p2 = LibraryFunc2();
int* data_out_1 = static_cast<int*>(*p2); // ?
int* data_out_2 = *reinterpret_cast<int**>(p2); // ?
根据显示的函数定义,不幸的是安全用法是:
void* tmpEvt;
X742_DecodeEvent(evtptr, &tmpEvt);
auto* Evt = static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
因为库函数假定 *Evt = Event;
*Evt
实际上是一个 void*
它可以修改的对象。它通常可以改为做更简单的事情:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL;
X742_DecodeEvent(evtptr, reinterpret_cast<void**>(&Evt));
但这是 C++ 标准未定义的行为,在某些体系结构上可能会做错事。
您可以通过将其包装在一个函数中来简化正确的方法:
inline CAEN_DGTZ_X742_EVENT_t* Get_X742_DecodeEvent(char* evtPtr)
{
void* tmpEvt;
X742_DecodeEvent(evtPtr, &tmpEvt);
return static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
}
使用以下代码段:
int n = 11;
int* c = &n;
void** v = &c;
我在 visual studio 中收到以下错误:
the value of type
int**
cannot be used to initialize an entity of typevoid **
.
这很好用:
int n = 11;
int* c = &n;
void* v = c;
但是这个代码片段是针对某人库中的一个更大的问题。
将变量转换为 void**
我做错了什么?
完整示例
使用caen digitizer library他们尝试从外围设备收集数据的方式有这个原型:
/******************************************************************************
* X742_DecodeEvent(char *evtPtr, void **Evt)
* Decodes a specified event stored in the acquisition buffer writing data in Evt memory
* Once used the Evt memory MUST be deallocated by the caller!
*
* [IN] EventPtr : pointer to the requested event in the acquisition buffer (MUST BE NULL)
* [OUT] Evt : event structure with the requested event data
* : return 0 = Success;
******************************************************************************/
int32_t X742_DecodeEvent(char *evtPtr, void **Evt);
这是实现:
int32_t X742_DecodeEvent(char *evtPtr, void **Evt) {
CAEN_DGTZ_X742_EVENT_t *Event;
uint32_t *buffer;
char chanMask;
uint32_t j,g,size;
uint32_t *pbuffer;
uint32_t eventSize;
int evtSize,h;
evtSize = *(long *)evtPtr & 0x0FFFFFFF;
chanMask = *(long *)(evtPtr+4) & 0x0000000F;
evtPtr += EVENT_HEADER_SIZE;
buffer = (uint32_t *) evtPtr;
pbuffer = (uint32_t *) evtPtr;
eventSize = (evtSize * 4) - EVENT_HEADER_SIZE;
if (eventSize == 0) return -1;
Event = (CAEN_DGTZ_X742_EVENT_t *) malloc(sizeof(CAEN_DGTZ_X742_EVENT_t));
if (Event == NULL) return -1;
memset( Event, 0, sizeof(CAEN_DGTZ_X742_EVENT_t));
for (g=0; g<X742_MAX_GROUPS; g++) {
if ((chanMask >> g) & 0x1) {
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j]= malloc(X742_FIXED_SIZE * sizeof (float));
if (Event->DataGroup[g].DataChannel[j] == NULL) {
for (h=j-1;h>-1;h++) free(Event->DataGroup[g].DataChannel[h]);
return -1;
}
}
size=V1742UnpackEventGroup(g,pbuffer,&(Event->DataGroup[g]));
pbuffer+=size;
Event->GrPresent[g] = 1;
}
else {
Event->GrPresent[g] = 0;
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j] = NULL;
}
}
}
*Evt = Event;
return 0;
}
我通过以下方式使用它:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL; // Creating my event pointer
//Doing some config of the device
X742_DecodeEvent(evtptr, &Evt); //Decode the event data for me to read (Throws error)
希望这能提供一些背景信息。
What am I doing wrong with casting a variable to void**?
没有将 int**
转换为 void**
的有效方法,因此您的尝试是错误的。
你可以做的是
int n = 11;
void* c = &n;
void** v = &c;
但是没有完整的例子,无法判断是否适用于你的问题。
这就是语言的工作原理。
void *
指针得到特殊处理:指向任意类型的指针可以转换为指向 void
的指针(只要这样做不会从指针)。
void **
得到 none 的特殊待遇。它只是一个普通的指针类型,比如 int **
.
int32_t X742_DecodeEvent(char *evtPtr, void **Evt)
既然你想传递 CAEN_DGTZ_X742_EVENT_t **
给你的函数,你应该相应地改变参数类型:CAEN_DGTZ_X742_EVENT_t **Evt
.
在评论中建议您使用 void ** v = (void**)&c;
。
虽然您可以可能使其在实践中发挥作用,但严格来说,对*v
的任何访问都将违反strict aliasing 并导致未定义的行为。我不会使用那个解决方案。
void**
表示指向 void*
对象的指针。但是该代码中没有 void*
对象指向! void**
并不意味着 "a pointer to any kind of pointer",所以请避免这样使用它。如果您有一个指向可能是 int*
、double*
等的指针,void*
是比 void**
更好的类型。更好的是模板或 std::variant
或 std::any
.
但是如果你必须使用一个使用 void**
的库来表示 "a pointer to a pointer to a type unknown at compile time" 或类似的东西,你可能需要创建一个 void*
指针来使用,或者可能需要添加强制转换来解决编译器不喜欢这种转换的事实(有充分的理由)。问题是,至少有两种合理的方法可以做到这一点! (他们最终会在许多常见的计算机体系结构上做完全相同的事情,但这并不能保证。)
// LibraryFunc1 takes a void** argument that somehow means an int* pointer.
// But which call is correct?
int* data_in = generate_data();
LibraryFunc1(reinterpret_cast<void**>(&data_in)); // ?
void* p1 = data_in;
LibraryFunc1(&p1); // ?
// LibraryFunc2 returns a void** argument that somehow means an int* pointer.
void** p2 = LibraryFunc2();
int* data_out_1 = static_cast<int*>(*p2); // ?
int* data_out_2 = *reinterpret_cast<int**>(p2); // ?
根据显示的函数定义,不幸的是安全用法是:
void* tmpEvt;
X742_DecodeEvent(evtptr, &tmpEvt);
auto* Evt = static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
因为库函数假定 *Evt = Event;
*Evt
实际上是一个 void*
它可以修改的对象。它通常可以改为做更简单的事情:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL;
X742_DecodeEvent(evtptr, reinterpret_cast<void**>(&Evt));
但这是 C++ 标准未定义的行为,在某些体系结构上可能会做错事。
您可以通过将其包装在一个函数中来简化正确的方法:
inline CAEN_DGTZ_X742_EVENT_t* Get_X742_DecodeEvent(char* evtPtr)
{
void* tmpEvt;
X742_DecodeEvent(evtPtr, &tmpEvt);
return static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
}