0

我正在编写一个简单的程序,它是关于在 C# 中使用链表的多项式。我遇到的问题是,每当它在 for 循环中创建一个新结构(节点)时,它都会给它与前一个节点相同的地址。我该如何解决?这是我的结构:

struct poly { public int coef; public int pow; public poly* link;} ;

这就是问题发生的地方:

for (; i < this.textBox1.Text.Length; i++)
{
    q = new poly();
    ...
    p->link = &q;
}

&q保持不变!

更新:

为了更清楚地说明,这里是完整的代码:

namespace PolyListProject
{
    unsafe public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();   
        }

        struct poly { public int coef; public int pow; public poly* link;} ;
        poly *start ;
        poly *p;

        private void button1_Click(object sender, EventArgs e)
        {
            string holder = "";
            poly q = new poly();
            start = &q;
            int i = 0;
            while (this.textBox1.Text[i] != ',')
            {
                holder += this.textBox1.Text[i];
                i++;
            }
            q.coef = int.Parse(holder);
            i++;
            holder = "";
            while (this.textBox1.Text[i] != ';')
            {
                holder += this.textBox1.Text[i];
                i++;
            }
            q.pow = int.Parse(holder);
            holder = "";
            p = start;
            //creation of the first node finished!
            i++;
            for (; i < this.textBox1.Text.Length; i++)
            {
                q = new poly();
                while (this.textBox1.Text[i] != ',')
                {
                    holder += this.textBox1.Text[i];
                    i++;
                }
                q.coef = int.Parse(holder);
                holder = "";
                i++;
                
                while (this.textBox1.Text[i] != ';'&& i < this.textBox1.Text.Length-1)
                {
                    holder += this.textBox1.Text[i];
                    if (i < this.textBox1.Text.Length-1)
                        i++;
                }
                q.pow = int.Parse(holder);
                holder = "";
                p->link = q;
            }
            p->link = null;
        }
    }
}

我们的教授要求我们用 C 来做,但我们决定用 C# 来做,但给它一个 C 的外观,因为没有人真正使用 C。

4

3 回答 3

2

好的,既然您肯定使用的是 C++,而不是 C#,我将用 C++ 来回答。

在这个函数中,q变量是(我假设),这个函数的本地指针。这意味着它的地址不会改变。

问题是您将指针的地址分配给p->link. 由于new poly()返回一个poly*已经(这是一个地址!)您不需要该地址。

尝试这个:

q = new poly();
 ... 
p->link = q;
于 2010-05-16T11:45:32.747 回答
1

问题解决了 :) 像这样:(但 q 是一个指针)

IntPtr newP = Marshal.AllocHGlobal(sizeof(poly));
poly* q = (poly*)newP.ToPointer();
// ......
p->link = q;
于 2010-05-17T17:15:32.870 回答
0

&q 的问题在于,结构实例 q 在方法运行时存在于执行堆栈中。即使您使用 new() 语法,该结构仍然在堆栈上。因此,地址总是相同的(当你从函数返回时将变得无效。)如果你想获得一个指向堆上结构的指针(不是 GC 堆,而是一个特殊的非托管内存区域),你需要使用AllocHGlobal分配内存,然后将其IntPtr转换为(poly*). 这是非托管内存,因此您还需要记住释放它。

一般来说,我认为尝试以这种方式使用 C# 是一个非常糟糕的主意,因为它会让 C# 和 C++ 程序员都感到困惑。不安全的语法在非常罕见的边界情况下很有用,您需要快速访问底层内存或某些互操作场景。使用它来实现具有 C 风格指针的数据结构是完全错误的。


这是一个具体的例子,以防上述不清楚。该操作q = new poly();只是用新初始化的 poly() 替换 q(堆栈上的局部变量)的内容。这更像是清除内存而不是分配一个新实例。令人困惑的原因是,在 C++ 中,结构和类在分配方面没有区别。C++ 中的 new() 总是在堆上分配。在 C# 中,分配位置通常由类型确定,而不是使用情况,因此当您在值类型(结构)上调用 new() 时,这是初始化它的简写,而不是在堆上为其分配内存。


你问了一个关于“固定”的问题,有一个很好的例子说明为什么你不应该使用不安全的 C#,认为它与 C 基本相同。在 C# 中,引用指针不同。最大的区别之一是,由于 C# 引用被垃圾收集,GC 几乎可以在任何时候决定劫持程序的执行并替换所有引用以指向新的内存位置。如果您使用通过指针引用引用的内存的不安全代码,则指针引用的对象可能会在指针未更新的情况下移动。为了解决这个问题,您可以将特定实例标记为“固定”,以便 GC 不会移动它。C# 编译器试图保护您免受自己的伤害。

于 2010-05-16T13:28:05.460 回答