如何将int **转换为void **?

时间:2019-07-09 21:35:38

标签: c++ casting void void-pointers

带有以下代码段:

int n = 11;
int* c = &n;
void** v = &c;

我在Visual Studio中收到以下错误:

  

类型int**的值不能用于初始化类型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)

希望这提供了一些上下文。

3 个答案:

答案 0 :(得分:4)

  

将变量强制转换为void **怎么办?

没有将int**转换为void**的有意义的方法,因此您尝试做的是错误的。

您可能会做的

int n = 11;
void* c = &n;
void** v = &c;

但是,如果没有完整的示例,就无法说出是否适用于您的问题。

答案 1 :(得分:3)

void**表示指向void*对象的指针。但是该代码中没有void*对象指向! void**并不表示“指向任何种类的指针的指针”,因此请避免这样使用。如果您有一个指向可能是int*,可能是double*等的指针,则void*void**更好。最好是模板或std::variantstd::any

但是,如果您必须使用使用void**来表示“指向编译时未知类型的指针的指针”之类的库,则可能需要创建一个{{1}使用}指针,或者可能需要添加强制转换以解决编译器不喜欢这种转换的事实(有充分的理由)。问题是,至少有两种合理的方法可以做到这一点! (他们最终将在许多常见的计算机体系结构上做完全相同的事情,但这不能保证。)

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*

但这是C ++标准未定义的行为,在某些体系结构上可能做错了事。

您可以通过将其包装在函数中来简化正确的方法:

CAEN_DGTZ_X742_EVENT_t* Evt = NULL;
X742_DecodeEvent(evtptr, reinterpret_cast<void**>(&Evt));

答案 2 :(得分:1)

这就是语言的工作原理。

void *指针得到特殊待遇:任意类型的指针都可以转换为指向void的指针(只要这样做不会从指针中删除cv-qualifiers

void **没有得到任何特殊待遇。它只是一个常规的指针类型,例如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并导致未定义的行为。我不会使用该解决方案。