【问题标题】:Using XOR to implement doubly linked list with one pointer per node使用异或实现每个节点一个指针的双向链表
【发布时间】:2011-12-29 21:57:54
【问题描述】:

我遇到了 XOR 双链表的问题,它有一个必须包含节点的 NEXT 和 PREV 指针的指针。我必须对指针的地址进行异或运算,但我不能。 我可以分配一个与两个地址异或的内存地址,但我无法为其地址获取值(这有分段错误错误):

int main(){
    int* ptr = new int;
    int *ptr2 = new int;
    ptr2 = (int*)((unsigned long)ptr ^ (unsigned long)ptr2);
    *ptr2= 5;        /here has segmentation fault
    cout <<*ptr2;    
    return 0;

为什么这段代码有错误?我该如何解决?


感谢您的回复,但我无法转移我的想法,我换句话来说我的问题: 通常我们有一个指针,它通过“new”(在 c++ 中)关键字为其分配内存空间。这个为我们的指针保留的地址是由操作系统决定的,对吗? 例如,指针指向它的地址是 0x8f3400b(这是可以保留的可用内存) 我想通过不使用 new 关键字来手动执行此操作,如下代码:

int* ptr1 = (int*) 0x2355;
int* ptr2 = (int*) 0x23ff;

现在我不知道地址 0x2355 和 0x23ff 是否可以保留? 然后我决定“new”这些指针,然后对它们进行异或,如下所示:

int* ptr1 = new int     //ptr1 is now manage by OS
int* ptr2 = new int     //like ptr1 ...

然后我想对这些指针进行异或运算并创建一个新空间来附加一个节点,该节点是第三个节点,但我无法正确寻址它,但是当我想评估它时发生分段错误:

int* ptr1 = new int;    // for example the address is X
int* ptr2 = new int;    // for example the address is Y
int* ptr3 = (int*)((unsigned long)ptr1 ^ (unsigned long)ptr2);    //the final address is X^Y

我该如何纠正这个问题? 我不知道如何使用 intptr_t 和其他请帮助我 谢谢

【问题讨论】:

  • 这永远行不通。是什么促使你尝试它?
  • 什么意思如何手动分配内存
  • 我假设您正在尝试这样做? en.wikipedia.org/wiki/XOR_linked_list
  • 别笑了:有一个XOR linked list 这样的东西,它实际上涉及将指针异或在一起。这家伙可能正在尝试使用这样的列表。我希望我能理解他想说的话,这可能很有趣。如果是英文就好了。
  • @GregHewgill:即使那篇文章有 这种形式的链表可能是不可取的:

标签: c++


【解决方案1】:

有一个非常丑陋的技巧(如果可行的话)可以让您实现一个双向链表,每个节点只有一个指针。正如你所说,它需要异或指针值。

This Wikipedia article 讨论它。

这几乎总是一个非常糟糕的主意。该语言不保证它完全可以工作。

如果必须这样做,请将指针值强制转换为 uintptr_tintptr_t(这些类型甚至不能保证存在,但它们可能会存在),在 &lt;stdint.h&gt;&lt;cstdint&gt; 中声明。

异或两个指针值的结果将不是是一个有效的指针,任何将它用作一个指针的尝试都会在你的脸上炸开(如果你幸运的话)。从这样的操作中获取有效指针的唯一方法是反转它,取回原始指针值。您的 *ptr2 = 5; 导致分段错误并不奇怪。

如果您将此作为一种练习,只是为了看看您是否可以让它发挥作用,请务必继续并玩得开心。

如果您认为您对此有一些实际要求,您没有。如果你想要一个双向链表,每个节点只有两个指针。或者,更好的是,由于您使用 C++ 进行编程,因此请使用标准库容器类之一。

【讨论】:

  • "该语言不保证它完全可以工作。"你能详细说明一下吗?如果指针是 reinterpret_cast 那么以后你只需要对整数做数学吗?这应该是安全的,并且在嵌入式系统上可以节省一些内存
  • @luskan:如果将异或指针值存储到指针对象中,它可能是一个陷阱表示,或者存储它的行为可以通过规范化它来改变它的表示。如果您仅将异或值存储在 uintptr_tintptr_t 类型的对象中,则可以,只要您曾经转换回指针类型的唯一 uintptr_t 值与通过转换导出的值相同指向[u]intptr_t 的有效指针值。但我认为该技术实际上需要将异或值存储为指针。
  • @KeithThompson:该技术不要求将值存储为指针,它只是试图达到一种折衷方案,即以更多处理为代价使用更少的内存。要存储的数据可以是指针或整数类型(在某些平台上可能需要更多处理——如果数据/地址必须存储在不同的寄存器中)但想法是,如果您更关心内存占用,您可以减少一点。
【解决方案2】:

永远不要这样做

如果您绝对想将指针转换为某种整数类型,请至少使用intptr_t(由&lt;cstdint&gt;&lt;stdint.h&gt; 头文件提供)。

为什么要xor指针?这是一个丑陋的把戏!它有点禁用编译器优化。

【讨论】:

    【解决方案3】:

    使用 turbo C 3.0 版,我们利用 XOR 实现了一个指针的双向链表。通过你的 cmets.... 'C' FINDMIND 的变更团队。

    /* Code developed by 'C' The Change Team of FINDMIND
       Prabhakaran D, Vaishnavi N K, N N Priya, guided by
       Mr.Sridhar Arumugaswamy */
    
    #include <stdio.h>
    #include <conio.h>
    
    struct Node {
       int data;
       unsigned int next;
    }*start, *end, *newNode;
    
    typedef struct Node NODE;
    
    int menu(){
       int choice;
       clrscr();
       printf("1.Add\n2.Display\n3.Exit\n");
       scanf("%d", &choice );
       fflush(stdin);
       return choice;
    }
    
    void add() {
       clrscr();
       newNode = ( NODE * ) malloc ( sizeof( NODE ) );
       newNode -> next = 0;
       printf("Enter the data to enter :");
       scanf("%d", &(newNode -> data) );
       fflush(stdin);
       if( start == NULL ) {
          start = end = newNode;
       } else {
          newNode -> next = (unsigned int)end ^ 0;
          end -> next = ( end -> next ^ 0 ) ^ ( unsigned int)newNode;
          end = newNode;
       }
    }
    
    void display() {
       NODE *temp, *curr, *prev;
       prev = curr = temp = NULL;
       clrscr();
       for ( curr = start; curr != end ; temp = prev ,\
       prev = curr , curr = ( NODE * ) ( curr -> next ^ (unsigned int)temp ) )
          printf("%d\n", curr -> data );
       printf("%d\n", curr -> data );
       getch();
    }
    
    void main() {
       int choice;
       choice = menu();
       do {
          switch( choice ) {
         case 1: add();
             break;
         case 2: display();
             break;
         case 3: printf("\n\nBye!!!");
             break;
         default: printf("Bug dude!!!");
          }
          choice = menu();
       } while(choice != 3);
    }
    

    【讨论】:

      猜你喜欢
      • 2014-12-13
      • 1970-01-01
      • 1970-01-01
      • 2013-10-29
      • 1970-01-01
      • 2020-11-30
      • 1970-01-01
      • 2013-06-15
      • 1970-01-01
      相关资源
      最近更新 更多