简体   繁体   English

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

[英]How do I cast int** to void**?

With the following snippet: 使用以下代码段:

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

I receive the following error in visual studio: 我在visual studio中收到以下错误:

the value of type int** cannot be used to initialize an entity of type void ** . 类型int**的值不能用于初始化void **类型的实体。

This works fine: 这很好用:

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

But this code snippet is for a larger problem in someone's library. 但是,此代码段是针对某人库中的较大问题。

What am I doing wrong with casting a variable to void** ? 将变量转换为void**我做错了什么?

Complete Example 完整的例子

Using the caen digitizer library the way they try to collect data from the peripheral device has this prototype: 使用caen数字化仪库 ,他们尝试从外围设备收集数据的方式有这个原型:

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

And this is the implementation: 这是实施:

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

I use this by: 我用这个:

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)

Hope this gives some context. 希望这给出了一些背景。

What am I doing wrong with casting a variable to void**? 将变量转换为void **,我做错了什么?

There is no meaningful way to convert int** to void** , so what you're trying to do is wrong. 没有有意义的方法将int**转换为void** ,所以你要做的是错误的。

What you may do is 你可能做的是

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

But without a complete example, it is not possible to say whether applies to your problem. 但如果没有一个完整的例子,就无法说明是否适用于您的问题。

void** means a pointer to a void* object. void**表示指向void*对象的指针。 But there is no void* object in that code to point at! 但是代码中没有void*对象指向! void** does NOT mean "a pointer to any kind of pointer", so please avoid using it as such. void**并不意味着“指向任何指针的指针”,因此请避免使用它。 If you have a pointer to something which might be an int* , might be a double* , or etc., void* is a better type than void** . 如果你有一个可能是int*东西的指针,可能是double* ,等等, void*是一个比void**更好的类型。 Even better would be a template or std::variant or std::any . 更好的是模板或std::variantstd::any

But if you have to use a library that is using void** to mean "a pointer to a pointer to a type unknown at compile time" or something like that, you might need to create a void* pointer to work with, or might need to add in casts to get around the fact that the compiler doesn't like this conversion (for good reason). 但是如果你必须使用一个使用void**的库来表示“指向编译时未知类型的指针的指针”或类似的东西,你可能需要创建一个void*指针来处理,或者可能需要添加强制转换以解决编译器不喜欢这种转换的事实(有充分理由)。 The problem is, there are at least two reasonable ways to do this! 问题是,至少有两种合理的方法可以做到这一点! (They will end up doing exactly the same thing on many common computer architectures, but this is not guaranteed.) (他们最终会在许多常见的计算机架构上做同样的事情,但这并不能保证。)

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

Based on the function definition shown, the safe usage is unfortunately: 根据显示的功能定义,不幸的是安全使用:

void* tmpEvt;
X742_DecodeEvent(evtptr, &tmpEvt);
auto* Evt = static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);

since the library function assumes at *Evt = Event; 因为库函数假定为*Evt = Event; that *Evt is actually a void* object it can modify. *Evt实际上是一个可以修改的void*对象。 It may usually work to do the simpler thing instead: 通常可以做更简单的事情:

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

but this is undefined behavior by the C++ Standard, and might do the wrong thing on some architectures. 但这是C ++标准的未定义行为,并且可能在某些体系结构上做错了。

You could make the correct way easier by wrapping it in a function: 您可以通过将其包装在函数中来使正确的方法更容易:

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

That's simply how the language works. 这就是语言的运作方式。

void * pointers get special treatment: a pointer to an arbitrary type can be converted to a pointer to void (as long as doing so doesn't remove cv-qualifiers from the pointer). void *指针得到特殊处理:指向任意类型的指针可以转换为指向void的指针(只要这样做不会从指针中删除cv限定符 )。

void ** gets none of that special treatment. void **没有那种特殊待遇。 It's just a regular pointer type, like int ** . 它只是一个常规指针类型,如int **


 int32_t X742_DecodeEvent(char *evtPtr, void **Evt) 

Since you want to pass CAEN_DGTZ_X742_EVENT_t ** to your function, you should change the parameter type accordingly: CAEN_DGTZ_X742_EVENT_t **Evt . 由于您要将CAEN_DGTZ_X742_EVENT_t **传递给您的函数,因此您应该相应地更改参数类型: CAEN_DGTZ_X742_EVENT_t **Evt


In comments you were suggested to use void ** v = (void**)&c; 在评论中,您被建议使用void ** v = (void**)&c; .

While you could probably make it work in practice, strictly speaking any access to *v would violate strict aliasing and cause undefined behavior. 虽然你很可能使其在实际工作中,严格来说任何接入*v违反严格别名 ,并导致不确定的行为。 I wouldn't use that solution. 我不会使用那个解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM