无法将 DWORD 转换为 long unsigned int

Cannot convert DWORD to long unsigned int

Error: Cannot convert DWORD* {aka unsigned int*} to 'long unsigned int*' for argument 1 to int tea_encrypt(long unsigned int*,)

代码如下:

bool CLZObject::Encrypt(DWORD * pdwKey)
{
    if (!m_bCompressed)
    {
        assert(!"not compressed yet");
        return false;
    }

    BYTE * pbBuffer = m_pbBuffer + sizeof(THeader);
    m_pHeader->dwEncryptSize = tea_encrypt((DWORD *) pbBuffer, (const DWORD *) pbBuffer, pdwKey, m_pHeader->dwCompressedSize + 19);
    return true;
}

从错误信息来看,tea_encrypt()的第一个参数是long unsigned int *类型。 (DWORD *) 明确地将 pbBuffer 转换为 unsigned int *.

虽然 long unsigned intunsigned int 是可能的,但这不是标准所要求的。如果它们与您的实现(即本例中的编译器)不是等效类型,则指向一个的指针不能隐式转换为指向另一个的指针。

为了将第一个参数传递给函数,需要隐式转换(从 unsigned int *long unsigned int *)。编译器抱怨,因为不允许隐式转换。

至于你做什么,显而易见的是用 long unsigned int * 替换 (DWORD *) (即将 pbBuffer 的值转换为函数期望的指针)。这将使您的代码编译。

代码是否会正确运行是另一回事。您没有为任何人提供足够的上下文来确定这一点。

要了解您面临的问题,您必须了解两种类型在概念上绝非相同(除非它只是一个 typedef)。根据语言,intlong 是两种不同的类型。尽管您的实施可能具有相同的大小,但它们不需要在所有实施中都相同。如果您的目标是可移植代码,假设它们大小相同会导致问题。怎么样?

假设我们有一个实现,其中 sizeof(int)4sizeof(long)8

int i = 0;
long *l = &i;   // good that the compiler rejects this

如果允许这样做,那么您将进入 undefined behaviour。假设 i 位于内存位置 2000,因为它是 4 字节大小,允许访问直到 2003,因为该内存由程序拥有。程序(mer)不知道除此之外的内容,因此无法访问。

|<------------- i ------------->|
+-------+-------+-------+-------+-------+-------+-------+-------+
| 0x00  | 0x00  | 0x00  | 0x00  |unknown|unknown|unknown|unknown|
+-------+-------+-------+-------+-------+-------+-------+-------+
  2000    2001    2002    2003    2004    2005    2006    2007
|<---------------------------- *l ----------------------------->|  // oops!

由于 long 的大小为 8,使 l 指向 i 的地址 (2000) 将意味着它将指向2000 并且如果您取消引用指针,即执行 *l 以读取其中的内容,它将尝试读取大小为 8long,并尝试访问 2004到 2007 年,除了阅读 2000 年到 2003 年之外。因此导致您出现未定义的行为。

避免像显式转换(类型转换)这样的黑客行为,以干净的方式进行。使用临时的。

void need_long(long *data) { /* some code */ }

int i = 0;
long l = i;     // temporary long to pass it to need_long
need_long(&l);

如果您可以接受不可移植性并且确信 intlong 大小相同,那么在您的实现中,您可以另外传递 -fpermissive 以允许此操作GCC 默认禁止的转换。

检查函数 tea_encrypt。此函数很可能期望 unsigned long 为 32 位(因为 DWORD 在 Windows 上,即使在 Win64 上也是如此),而 unsigned long 在您的系统上可能是 64 位。您应该修复该功能。最好的方法是将要加密的缓冲区的类型 unsigned long 更改为 uint32_t 以明确确定该类型的 32 位。 uint32_t * 应该与 DWORD* 兼容,即使在您的系统上也是如此。