Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';glibc memmove中有符号int的强制转换的目的是什么?_C_Language Lawyer_Glibc - Fatal编程技术网

什么';glibc memmove中有符号int的强制转换的目的是什么?

什么';glibc memmove中有符号int的强制转换的目的是什么?,c,language-lawyer,glibc,C,Language Lawyer,Glibc,是的 unsigned long int dstp = (long int) dest; unsigned long int srcp = (long int) src; /* This test makes the forward copying code be used whenever possible. Reduces the working set. */ if (dstp - srcp >= len) /* *Unsigned* compare! */

是的

unsigned long int dstp = (long int) dest;
unsigned long int srcp = (long int) src;

/* This test makes the forward copying code be used whenever possible.
   Reduces the working set.  */
if (dstp - srcp >= len)       /* *Unsigned* compare!  */
  {
    /* Copy from the beginning to the end.  */

我理解他们为什么一开始就要麻烦地转换到long:通过比较指向(可能)不同对象的指针来避免未定义的行为。显然,他们必须使用无符号的long来进行实际的比较


但是为什么他们首先强制转换为长整型,然后隐式转换为无符号长整型?

复制奇数长度的字符串就是复制613字节, 但是为了提高速度,memcpy()以32位块实现

如果将32位整数写入奇数地址,一些较旧的处理器(如68000)会崩溃


铸造是为了安全。这项工作是由汇编程序完成的,如果需要可以添加额外的pad字节来防止这种情况。

首先,传递到函数中的参数类型为
void*
const void*
。为了以可比较的方式确定地址,将它们转换为整数类型(
long int
)。第一次强制转换执行整数转换,以便可以对
void*
指针进行数值比较

其次,一些非ANSI编译器可能以非统一的方式实现从
void*
到整数类型的隐式强制转换,并且可能会失去一些精度。在许多平台上,
long
的大小与
void*
的大小相同(尽管并非在所有平台上都是如此),从
void*
转换为
long
是表示地址的合适方式

第三,从
long int
unsigned long int
的转换有两个目的:确保在比较过程中大地址不会被误认为负数,并为非ANSI编译器提供更好的安全性。代码中引用的函数与
dest
src
中的内存对齐和重叠内存区域有关,用于确定内存移动是从开始到结束还是从结束到开始。这里使用无符号比较来更好地评估内存区域重叠的可能性,以及如何适当地处理它


某些非ANSI编译器可能无法正确地直接从
void*
转换为
无符号长整型
(取决于实现),并可能截断指针。从
void*
long int
unsigned long int
的转换应该在每一步保留位表示,这样实际地址就不会损坏。

这是一种旧的位攻击。您可以检查一个有符号的值是否在
0的范围内,这是没有意义的,地址是无符号的,我的问题是一行完全独立的代码:
unsigned long int dstp=(long int)dest为什么首先强制转换为有符号,然后才转换为无符号?“这是为了通过比较指向(可能)不同对象的指针来避免未定义的行为”-我怀疑这是原因。根据C标准,此函数中的许多内容都是未定义的行为。glibc面向的平台范围很窄,并且依赖于gcc的特定编译器行为,而这在C标准中没有涵盖。例如,
(long int)dest
将在64位窗口中导致UB。@user3528438“`len-=(-dstp)%OPSIZ;`强烈依赖于2的补码表示。”--C标准要求在重要的时候对无符号类型的所有操作都遵循2的补码算法。顺便说一句,包括有符号类型的强制转换。关于这方面的更多信息,这不是我要问的,我的问题是一行完全独立的代码:
unsigned long int dstp=(long int)dest为什么先强制转换为已签名,然后再转换为未签名?查看您发布的源代码,有许多评论认为对齐是主要原因之一。但除此之外,传递到函数中的参数被声明为
void*
const void*
,需要转换为可比较的整数类型(在本例中为
long int
),然后才能重新解释为
无符号长int
。(
a1
a2
分别是
#定义扩展到
dest
src
宏。)至于long int和long int的区别,我想两者都是32位?在任何情况下,尽管您描述的现象是真实的,并且有很好的文档记录,但我不明白它对原因有什么影响,如果有的话,对于强制转换。这解释了指针为何转换为整数类型,并解释了变量类型为何为
无符号长int
而不是
长int
,但没有解释指针为何不直接转换为
无符号长int
,所以没有真正回答这个问题。这并没有真正解决为什么代码不会直接转换为
unsigned long
。我已经更新了我的答案。我在第二点中提到了它(非ANSI编译器以非统一的方式进行转换),但我在最后一段中对此进行了明确的扩展。。。这是一个猜测,还是你有什么东西支持它?我会非常惊讶的。(请特别注意,问题注释中提到的changelog条目不支持它。)好的,这不适用于这里讨论的代码,即使是这样,中间转换到
long
也不会有任何效果,因为
long
unsigned long
始终具有相同的大小。如果从一个指针到其中一个指针的转换被截断,那么从同一个指针到另一个指针的转换也会被截断。