【问题标题】:Cannot convert DWORD to long unsigned int无法将 DWORD 转换为 long unsigned int
【发布时间】:2015-03-27 06:12:58
【问题描述】:

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

【问题讨论】:

  • 您使用的是什么版本的 C++?
  • 我尝试用密钥 LZO 制作一个转换器,一个解密器 Iso。我使用 c++ 11 因为我们定义的 CFLAGS -std=c++11
  • 哦,不要发布文字图片,也不要发布链接(可能会过时)。
  • 我不是在问你的整个程序在做什么,我是在问你试图做什么导致这个错误。至少编辑您的问题以包含相关代码,或者更好地创建一个Minimal, Complete, and Verifiable Example 并向我们展示。
  • 现在我编辑了这篇文章,抱歉snipet,但我是新来的。而且我不知道如何编写代码。谢谢

标签: c++ pointers type-conversion


【解决方案1】:

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

假设我们有一个实现,其中sizeof(int) 是4,sizeof(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,并且如果您取消引用指针,即执行@ 987654342@ 要读取其中的内容,它会尝试读取大小为 8 的 long,通过尝试访问 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);

如果您对不可移植性感到满意并且确信int 和long 的大小相同,那么在您的实现中,您可以另外传递-fpermissive 以允许GCC 默认禁止的这种转换。

【讨论】:

  • -fpermissive 而不是-fpermissible
  • @MikeKinghan 你是对的,当时很仓促!谢谢你:)
  • 您似乎在 pastebin.com 上的 pastebin.com/LKbzneJR 上发布了您要编译的代码。只要您在 Windows 上编译它,它就应该可以工作。这个问题是由如果使用 gcc 编译为 64 位代码会中断的茶代码引起的。 (它适用于 32 位模式 (-m32) 的 gcc 和 32 位模式的 Visual C++)。将unsigned long 替换为unsigned int 在TEA 代码中 以解决您的问题,或编译为32 位程序。
  • @legends2k 事实上,我想将此作为评论发布在 my 答案下方,而不是您的答案下方。对我造成的混乱感到抱歉。尽管如此,OP显然找到了它,并接受了我的回答。
  • 很好,没有问题。
【解决方案2】:

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

【讨论】:

  • 非常感谢,我的 tea_encrypt 函数被定义为 unsifned long int。我在 unsigned int 中更改了它,现在它可以正常工作了
【解决方案3】:

从错误消息来看,tea_encrypt() 的第一个参数是long unsigned int * 类型。 (DWORD *) 将pbBuffer 显式转换为unsigned int *。

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多