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;
}
答案 0 :(得分:1)
要了解您所面临的问题,您必须明白,从概念上讲,这两种类型永远不会相同(除非它只是typedef
)。 int
和long
根据语言有两种不同的类型。虽然您的实现可能具有相同的大小,但它们在所有实现中都不一定相同。如果您的目标是移植代码,那么假设它们的大小相同会导致问题。怎么样?
假设我们的实施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
)将意味着它{&#39} ll指向2000
,如果您取消引用指针,即执行*l
以阅读其中的内容,则会尝试读取long
大小8
通过尝试访问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默认禁止。
答案 1 :(得分:0)
从错误消息中,tea_encrypt()
的第一个参数是long unsigned int *
类型。 (DWORD *)
明确将pbBuffer
转换为unsigned int *
。
虽然long unsigned int
和unsigned int
有可能,但标准不要求这样做。如果它们不是您的实现的等效类型(在这种情况下是编译器),则指向一个的指针不能隐式转换为指向另一个的指针。
为了将第一个参数传递给函数,需要隐式转换(从unsigned int *
到long unsigned int *
)。编译器抱怨,因为不允许隐式转换。
关于你做了什么,显而易见的是用(DWORD *)
替换long unsigned int *
(即将pbBuffer的值转换为函数所期望的指针)。这将使您的代码得到编译。
代码是否会正常运行是另一回事。您没有提供足够的上下文供任何人确定。
答案 2 :(得分:0)
检查功能tea_encrypt。该函数很可能期望unsigned long
为32位(因为DWORD在Windows上,即使在Win64上),而unsigned long
可能是您系统上的64位。你应该修复这个功能。最好的方法是将缓冲区的类型unsigned long
更改为加密到uint32_t
,以明确确定该类型的32位。 uint32_t *
应该与DWORD*
兼容,即使在您的系统上也是如此。