64位减法结果为32位整数

时间:2011-10-28 17:52:23

标签: c++ 64-bit

有一个名为“Compare”的现有函数,它是

int compare(void* A, void* B) { return (int)A - (int)B; }

我知道这是一个残暴的做法,但我没有编写那段代码,而且它已经在很多地方使用过了。但是这段代码在64位下产生了编译错误,因为void *不再是32位,所以我将代码修改为以下内容。

int compare(void* A, void* B) { return (long long)A - (long long)B; }

此函数在当前64位Linux体系结构下返回错误结果的可能性是多少?那么,两个虚拟地址分开超过0x7FFFFFFF的可能性是多少?

7 个答案:

答案 0 :(得分:7)

我想你想要

int compare(void* A, void* B) { return (A > B) - (A < B); }

答案 1 :(得分:3)

在我的linux机器上,这是一个例子。

我有一份tcsh正在运行。它的进程ID为9732.我们可以通过检查/proc/<pid>/maps来查看它的内存映射。

从下表中,我们可以看到堆数据存储在0x01e30000左右,而堆栈数据存储在0x7fffca3e6000左右。所以在一个简单的例子中,如果你将malloc分配的指针与堆栈指针进行比较,你会看到指针的显着差异。

[1:02pm][wlynch@charcoal Harrow] cat /proc/9732/maps
00400000-0045a000 r-xp 00000000 09:00 44826689                           /bin/tcsh
0065a000-0065e000 rw-p 0005a000 09:00 44826689                           /bin/tcsh
0065e000-00674000 rw-p 00000000 00:00 0 
0085d000-0085f000 rw-p 0005d000 09:00 44826689                           /bin/tcsh
01e30000-01f78000 rw-p 00000000 00:00 0                                  [heap]
38a3c00000-38a3c1e000 r-xp 00000000 09:00 16253177                       /lib64/ld-2.12.so
38a3e1e000-38a3e1f000 r--p 0001e000 09:00 16253177                       /lib64/ld-2.12.so
38a3e1f000-38a3e20000 rw-p 0001f000 09:00 16253177                       /lib64/ld-2.12.so
38a3e20000-38a3e21000 rw-p 00000000 00:00 0 
38a4400000-38a4575000 r-xp 00000000 09:00 16253179                       /lib64/libc-2.12.so
38a4575000-38a4775000 ---p 00175000 09:00 16253179                       /lib64/libc-2.12.so
38a4775000-38a4779000 r--p 00175000 09:00 16253179                       /lib64/libc-2.12.so
38a4779000-38a477a000 rw-p 00179000 09:00 16253179                       /lib64/libc-2.12.so
38a477a000-38a477f000 rw-p 00000000 00:00 0 
38a4800000-38a4802000 r-xp 00000000 09:00 16253186                       /lib64/libdl-2.12.so
38a4802000-38a4a02000 ---p 00002000 09:00 16253186                       /lib64/libdl-2.12.so
38a4a02000-38a4a03000 r--p 00002000 09:00 16253186                       /lib64/libdl-2.12.so
38a4a03000-38a4a04000 rw-p 00003000 09:00 16253186                       /lib64/libdl-2.12.so
38af000000-38af01d000 r-xp 00000000 09:00 16253156                       /lib64/libtinfo.so.5.7
38af01d000-38af21d000 ---p 0001d000 09:00 16253156                       /lib64/libtinfo.so.5.7
38af21d000-38af221000 rw-p 0001d000 09:00 16253156                       /lib64/libtinfo.so.5.7
38b0c00000-38b0c58000 r-xp 00000000 09:00 16253191                       /lib64/libfreebl3.so
38b0c58000-38b0e57000 ---p 00058000 09:00 16253191                       /lib64/libfreebl3.so
38b0e57000-38b0e59000 rw-p 00057000 09:00 16253191                       /lib64/libfreebl3.so
38b0e59000-38b0e5d000 rw-p 00000000 00:00 0 
38b1000000-38b1007000 r-xp 00000000 09:00 16253192                       /lib64/libcrypt-2.12.so
38b1007000-38b1207000 ---p 00007000 09:00 16253192                       /lib64/libcrypt-2.12.so
38b1207000-38b1208000 r--p 00007000 09:00 16253192                       /lib64/libcrypt-2.12.so
38b1208000-38b1209000 rw-p 00008000 09:00 16253192                       /lib64/libcrypt-2.12.so
38b1209000-38b1237000 rw-p 00000000 00:00 0 
7f03aa9a0000-7f03aa9ac000 r-xp 00000000 09:00 16252957                   /lib64/libnss_files-2.12.so
7f03aa9ac000-7f03aabab000 ---p 0000c000 09:00 16252957                   /lib64/libnss_files-2.12.so
7f03aabab000-7f03aabac000 r--p 0000b000 09:00 16252957                   /lib64/libnss_files-2.12.so
7f03aabac000-7f03aabad000 rw-p 0000c000 09:00 16252957                   /lib64/libnss_files-2.12.so
7f03aabbc000-7f03aabc3000 r--s 00000000 09:00 5769665                    /usr/lib64/gconv/gconv-modules.cache
7f03aabc3000-7f03b0a54000 r--p 00000000 09:00 5506757                    /usr/lib/locale/locale-archive
7f03b0a54000-7f03b0a58000 rw-p 00000000 00:00 0 
7f03b0a5b000-7f03b0a67000 r--p 00000000 09:00 5510943                    /usr/share/locale/en/LC_MESSAGES/tcsh
7f03b0a67000-7f03b0a68000 rw-p 00000000 00:00 0 
7fffca3e6000-7fffca3fb000 rw-p 00000000 00:00 0                          [stack]
7fffca3ff000-7fffca400000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

答案 2 :(得分:2)

这看起来像一个排序比较函数,所以最重要的是结果的符号。

int compare(void *A, void* B)
{
  if (A < B) return -1;
  if (A > B) return 1;
  return 0;
 }

答案 3 :(得分:0)

你不应该返回一个int,而是一个uintptr_t。确保设置为此函数的变量也是uintptr_t。

uintptr_t compare(void* A, void* B) { return (uintptr_t)A - (uintptr_t)B; }

如果由于某种原因无法执行此操作,则应检查值是否在范围内,否则抛出错误。机会可能非常小,但这并不意味着它是一个例外情况。

答案 4 :(得分:0)

int compare (void*p, void*q) { return (p==q)?0:((char*)p < (char*)q)?-1:1; }

答案 5 :(得分:0)

如果您碰巧比较堆栈和堆上的地址,我会说差异很可能大于那个(因为堆通常从底部长大,堆栈从顶部向下增长)。

不是返回int,而是返回ptrdiff_t,它的名字暗示是一个足以保持指针差异的整数类型。尽管我选择了char*而不是int,但仍然需要投射,因为它允许您使用static_cast

ptrdiff_t compare(void* A, void* B) { return static_cast<char*>(A) - static_cast<char*>(B); }

最后,如果你在C qsort中使用它,只需采用简单的方法:使用std::sort,它可以使用单个<,而不需要在所有!

答案 6 :(得分:0)

首先:只有指针指向同一个数组时,才会定义指针比较。但我认为只要它在实践中起作用你就不在乎。

在x86和AMD64上,<>指针之间的比较最有可能在实践中发挥作用。但是由于int溢出,基于差异的方法可能会失败。

  

有一个名为“Compare”的现有函数,它是

int compare(void* A, void* B) { return (int)A - (int)B; }

在32位系统上已经破坏了这一点,其中指针存在高位集。这不仅会导致奇怪的排序,而且会违反订单所需的传递属性。在Windows上,这可能发生在使用/LARGEADDRESSAWARE的应用程序(允许3GB的用户模式地址空间)。我不太了解Linux,知道它是否会在那里发生。

所以你应该在32位系统上使用Ben Voigt的代码。