使用 `memcpy()` 为指针分配地址
Using `memcpy()` to assign a pointer an address
是
memcpy( ptr, &value, sizeof(char *) );
与
相同
ptr = &value;
.......
我以前从未见过 memcpy()
曾经这样做过。
看来我应该用短语 "Well, you're not wrong." 来回应这段代码的开发者,这似乎比需要的要多一些。
编辑:注意 ptr
是 void * ptr
似乎很重要。 value
是 double value
.
Edit2:对于那些有兴趣和我一起深入研究这个问题的人,请继续阅读。这段代码被静态分析标记为潜在的缓冲区溢出。静态分析担心目标缓冲区 ptr
可能没有足够的 space 来保存 sizeof(char *)
的信息。
我没有处理它给我的问题,而是试图准确理解这个 memcpy()
做了什么(谢谢你帮助我)。一旦我理解了发生了什么,我就必须理解为什么分配给 memcpy()
的内存大小是 sizeof(char *)
;这个 memcpy()
所在的函数被调用了一次,那一次看起来像这样:
SdmJniGetPointer(blah, blah, &ptr)
意味着 ptr
在这个函数中的实际值,在 memcpy()
调用中,是另一个指针的地址!
之前的开发人员 memcpy()
数据量 sizeof(char *)
对我来说很奇怪,因为这个系统是在 32 位和 64 位机器上编译的。然而,因为他将指针 (&ptr
) 的地址作为 ptr
传递到函数中,他不仅根据系统架构避免了从 4 字节指针到 8 字节指针的转换,而且也完全按照他的意思使用它(我认为)。最后,在 64 位系统上,所有 double value
都被复制到 ptr
指向的地址,这实际上是指向不同指针 (&ptr
) 的地址,并且在 32 位机器上,一半被复制到位置 ptr
,实际上是 &ptr
。现在我只需要弄清楚 double value
真正代表什么,以及为什么他可以将它一分为二。
如果那没有意义,我会再试一次,但感觉就像他在盗梦空间指针一样。 =)
不,完全不同。让我们添加一些类型:
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 *
(假设value
是,根据sizeof
)。
假设 ptr
是 char **
(或者您将其更改为获取 ptr
的地址:&ptr
)并正确初始化,我认为没有实际问题 这里。但是,此代码禁止编译器进行类型检查,并且可能比简单的赋值要慢。
如果源和目标具有不同的类型(正如编辑所暗示的),它也可能会出现别名问题。它还可能会禁止优化。
哦,而且:该代码更难 read/manually verify/understand,IOW:维护(如评论和我自己的编辑所示)。也许开发人员通过混淆来确保工作安全?
编辑:
编辑后添加类型信息:该代码更糟糕。它甚至不使用相同的类型。我的建议:把作者踢到真正受伤的地方,然后 非常 小心地重写代码。注意:谁写了这样的代码,很可能在其他地方写了更多废话。
赋值符号比使用 memcpy 更简洁和可读,并允许编译器优化。 =
表示赋值,而 memcpy 只是复制内存。
你应该坚持 =
作业
这会更改指针 ptr
指向的 地址 :
ptr = &value;
这会更改指针 ptr
指向的地址处的 数据:
memcpy(ptr, &value, sizeof(char*));
在第二种情况下,ptr
仍然指向与调用前相同的地址。所以它们绝不相同。
是
memcpy( ptr, &value, sizeof(char *) );
与
相同ptr = &value;
.......
我以前从未见过 memcpy()
曾经这样做过。
看来我应该用短语 "Well, you're not wrong." 来回应这段代码的开发者,这似乎比需要的要多一些。
编辑:注意 ptr
是 void * ptr
似乎很重要。 value
是 double value
.
Edit2:对于那些有兴趣和我一起深入研究这个问题的人,请继续阅读。这段代码被静态分析标记为潜在的缓冲区溢出。静态分析担心目标缓冲区 ptr
可能没有足够的 space 来保存 sizeof(char *)
的信息。
我没有处理它给我的问题,而是试图准确理解这个 memcpy()
做了什么(谢谢你帮助我)。一旦我理解了发生了什么,我就必须理解为什么分配给 memcpy()
的内存大小是 sizeof(char *)
;这个 memcpy()
所在的函数被调用了一次,那一次看起来像这样:
SdmJniGetPointer(blah, blah, &ptr)
意味着 ptr
在这个函数中的实际值,在 memcpy()
调用中,是另一个指针的地址!
之前的开发人员 memcpy()
数据量 sizeof(char *)
对我来说很奇怪,因为这个系统是在 32 位和 64 位机器上编译的。然而,因为他将指针 (&ptr
) 的地址作为 ptr
传递到函数中,他不仅根据系统架构避免了从 4 字节指针到 8 字节指针的转换,而且也完全按照他的意思使用它(我认为)。最后,在 64 位系统上,所有 double value
都被复制到 ptr
指向的地址,这实际上是指向不同指针 (&ptr
) 的地址,并且在 32 位机器上,一半被复制到位置 ptr
,实际上是 &ptr
。现在我只需要弄清楚 double value
真正代表什么,以及为什么他可以将它一分为二。
如果那没有意义,我会再试一次,但感觉就像他在盗梦空间指针一样。 =)
不,完全不同。让我们添加一些类型:
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 *
(假设value
是,根据sizeof
)。
假设 ptr
是 char **
(或者您将其更改为获取 ptr
的地址:&ptr
)并正确初始化,我认为没有实际问题 这里。但是,此代码禁止编译器进行类型检查,并且可能比简单的赋值要慢。
如果源和目标具有不同的类型(正如编辑所暗示的),它也可能会出现别名问题。它还可能会禁止优化。
哦,而且:该代码更难 read/manually verify/understand,IOW:维护(如评论和我自己的编辑所示)。也许开发人员通过混淆来确保工作安全?
编辑:
编辑后添加类型信息:该代码更糟糕。它甚至不使用相同的类型。我的建议:把作者踢到真正受伤的地方,然后 非常 小心地重写代码。注意:谁写了这样的代码,很可能在其他地方写了更多废话。
赋值符号比使用 memcpy 更简洁和可读,并允许编译器优化。 =
表示赋值,而 memcpy 只是复制内存。
你应该坚持 =
作业
这会更改指针 ptr
指向的 地址 :
ptr = &value;
这会更改指针 ptr
指向的地址处的 数据:
memcpy(ptr, &value, sizeof(char*));
在第二种情况下,ptr
仍然指向与调用前相同的地址。所以它们绝不相同。