Is
memcpy( ptr, &value, sizeof(char *) );
同
ptr = &value;
.....
我以前从未见过memcpy()
曾经这样做过。似乎我应该用短语"好吧,你没有错"来回应这段代码的开发人员。这似乎比它需要的要罗嗦一些。
编辑:似乎重要的是要注意ptr
void * ptr
。 value
是double value
.
编辑2:对于那些有兴趣和我一起关注这个问题的人,请继续阅读。 静态分析将这段代码标记为潜在的缓冲区溢出。 静态分析担心目标缓冲区ptr
可能没有足够的空间来保存sizeof(char *)
的信息。
我没有处理它给我的问题,而是试图确切地了解这个memcpy()
做了什么(谢谢你帮助我(。 一旦我明白了发生了什么,我就必须明白为什么给memcpy()
的记忆大小是sizeof(char *)
的;此memcpy()
所在的函数称为一次,那一次它看起来像这样:
SdmJniGetPointer(blah, blah, &ptr)
这意味着此函数中和memcpy()
调用中ptr
的实际值是另一个指针的地址!
对我来说很奇怪的是,以前的开发人员会memcpy()
sizeof(char *)
的数据量,因为这个系统是在 32 位和 64 位机器上编译的。 然而,因为他将指针的地址(&ptr
(作为ptr
传递到函数中,他不仅根据系统架构规避了从4字节指针到8字节指针的转变,而且完全按照他的意思使用它(我认为(。 最后,在 64 位系统上,所有double value
都被复制到 ptr
指向的地址中,这实际上是指向不同指针 (&ptr
的地址(,而在 32 位机器上,其中一半被复制到位置ptr
这真的很&ptr
。 现在我只需要弄清楚double value
真正代表什么,以及为什么他可以将其一分为二。
如果这没有意义,我会再试一次,但感觉就像他在启动指针。 =(
这会更改指针ptr
指向的地址:
ptr = &value;
这将更改指针ptr
指向的地址处的数据:
memcpy(ptr, &value, sizeof(char*));
在第二种情况下,ptr
仍指向与呼叫前相同的地址。所以它们绝不是相同的。
不,这是绝对不同的。 让我们添加一些类型:
char *addr;
char **ptr = &addr;
char *value = "Hello";
memcpy(ptr, &value, sizeof(char *));
// Equivalent to...
*ptr = value;
如果可以使用=
,最好避免memcpy()
。
除此之外,如果类型不正确,那么=
将生成正确的诊断,而memcpy()
会很乐意使您的程序崩溃或更糟。
给定类型,
double value, value2;
void *ptr = &value2;
// This copies `value` into `value2`.
memcpy(ptr, &value, sizeof(double));
使用sizeof(char *)
是错误的,因为如果要复制double
,则应sizeof(double)
。
从理论上讲,你可以做一些更深奥的事情,但我会忽略这种可能性。
memcpy
就像
*ptr = value;
所以ptr
必须指向一个char *
(根据sizeof
,假设value
是(。
假设ptr
是char **
的(或者您将其更改为采用 ptr
: &ptr
的地址(并正确初始化,我认为这里没有实际问题。但是,此代码禁止编译器进行类型检查,并且可能比简单赋值慢。
如果源和目标具有不同的类型(如编辑所暗示的那样(,它也可能会出现锯齿问题。它还可能会禁止优化。
哦,还有:该代码更难阅读/手动验证/理解,IOW:维护(如评论和我自己的编辑所示(。也许开发人员是通过混淆来追求工作安全?
编辑:
编辑添加类型信息后:该代码更糟。它甚至不使用相同的类型。我的建议是:踢作者真正受伤的地方,然后非常小心地重写代码。注意:无论谁写这样的代码,很可能会在其他地方写更多的废话。
赋值表示法比使用 memcpy 更加简洁易读,并允许编译器优化。 =
意味着分配,而memcpy只是复制内存。
你应该坚持=
作业