代码之家  ›  专栏  ›  技术社区  ›  lornova

嵌套静态类型转换和常量类型转换

  •  1
  • lornova  · 技术社区  · 6 年前

    我有如下系统调用:

    int transfer(int handle, int direction, unsigned char *data, int length);
    

    我编写了以下两个函数:

    int input(int handle, void* data, int length)
    {
        return transfer(handle, 1, static_cast<unsigned char*>(data), length);
    }
    
    int output(int handle, const void* data, int length)
    {
        return transfer(handle, 0, static_cast<unsigned char*>(const_cast<void*>(data)), length);
    }
    

    我不喜欢嵌套的 const_cast static_cast ,是否有方法从 const void* unsigned char* 一步一步?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Xirema    6 年前

    使用C样式的强制转换将生成相同的程序集。 As seen in Compiler Explorer :

    //Source #1
    int transfer(int handle, int direction, unsigned char *data, int length);
    int input(int handle, void* data, int length)
    {
        return transfer(handle, 1, static_cast<unsigned char*>(data), length);
    }
    
    int output(int handle, const void* data, int length)
    {
        return transfer(handle, 0, static_cast<unsigned char*>(const_cast<void*>(data)), length);
    }
    
    //Source #2
    int transfer(int handle, int direction, unsigned char *data, int length);
    int input(int handle, void* data, int length)
    {
        return transfer(handle, 1, (unsigned char*)data, length);
    }
    
    int output(int handle, const void* data, int length)
    {
        return transfer(handle, 0, (unsigned char*)data, length);
    }
    
    //Assembly (both)
    input(int, void*, int):
            mov     ecx, edx
            mov     rdx, rsi
            mov     esi, 1
            jmp     transfer(int, int, unsigned char*, int)
    output(int, void const*, int):
            mov     ecx, edx
            mov     rdx, rsi
            xor     esi, esi
            jmp     transfer(int, int, unsigned char*, int)
    

    所以很明显,只使用C样式的演员表就可以解决你的问题。

    但是,你 不应该 使用C样式的演员表

    C++编译器的冗长性的原因是确保你不犯错误。当维护人员看到您的代码时,他们看到 const_cast 以及 static_cast ,因为这样编写代码会通知读者 const -指针是有意的和期望的行为。代码维护人员应该看到这些强制转换,并假定代码背后有意图,而不必猜测您是否直接从 const void* unsigned char* 会涉及到不明确行为的风险。您的示例可能不包含ub(因为您指定了 transfer 是治疗 data direction 是0),但重要的是,任何其他需要对代码进行更改的人都必须理解您的编码实践的谨慎性。

        2
  •  0
  •   JHBonarius    6 年前

    你不想要 data 做个警察。如果 transfer 试图修改它? 拥有本地副本更安全:

    #include <cstring>
    int output(int handle, const void* data, int length)
    {
        unsigned char localData[length];
        std::memcpy(localData, data, length);
        return transfer(handle, 0, localData, length);
    }
    

    编辑:通过阅读评论,这是Shlublu建议的……