什么';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
始终具有相同的大小。如果从一个指针到其中一个指针的转换被截断,那么从同一个指针到另一个指针的转换也会被截断。