Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.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
C# 如何更改循环中新结构的地址?_C#_Struct_Loops_Unsafe - Fatal编程技术网

C# 如何更改循环中新结构的地址?

C# 如何更改循环中新结构的地址?,c#,struct,loops,unsafe,C#,Struct,Loops,Unsafe,我正在写一个关于多项式的简单程序,它使用C#中的链表。我遇到的问题是,每当它在for循环中创建一个新的结构(节点)时,它都会给它提供与前一个节点相同的地址。我该如何解决这个问题?这是我的结构: struct poly { public int coef; public int pow; public poly* link;} ; 这里是问题发生的地方: for (; i < this.textBox1.Text.Length; i++) { q = new poly();

我正在写一个关于多项式的简单程序,它使用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;
}

P教授的要求我们在C中做,但是我们决定在C中做,但C看起来,因为没有人真正使用C。< / P> < P>好的,因为你肯定使用C++,而不是C++,我将用C++来回答。 在这个函数中,
q
变量是(我假设),一个指向这个函数的本地指针。这意味着它的地址不会改变

问题是您正在将指针的地址分配给
p->link
。因为
newpoly()
已经返回了一个
poly*
(这是一个地址!),所以您不需要该地址

试试这个:

q = new poly();
 ... 
p->link = q;

<>当然,既然你肯定使用C++,而不是C++,我将用C++来回答。 在这个函数中,
q
变量是(我假设),一个指向这个函数的本地指针。这意味着它的地址不会改变

问题是您正在将指针的地址分配给
p->link
。因为
newpoly()
已经返回了一个
poly*
(这是一个地址!),所以您不需要该地址

试试这个:

q = new poly();
 ... 
p->link = q;

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

一般来说,我认为用C语言来这样做是一个非常坏的想法,因为它对C和C++程序员都是混淆的。不安全语法在极少数需要快速访问底层内存或某些操作间场景的情况下非常有用。用它来实现带有C风格指针的数据结构是完全错误的


这里有一个具体的例子,以防上面不清楚。操作
q=newpoly()只是用新初始化的poly()替换q(堆栈上的局部变量)的内容。这更类似于清除内存,而不是分配新实例。之所以混淆是因为,在C++中,在分配时,结构和类之间没有区别。一个新的()C++总是在堆上分配。在C#中,分配位置通常由类型决定,而不是使用情况,因此当您对值类型(struct)调用new()时,这是初始化它的缩写,而不是在堆上为它分配内存



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

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

一般来说,我认为用C语言来这样做是一个非常坏的想法,因为它对C和C++程序员都是混淆的。不安全语法在极少数需要快速访问底层内存或某些操作间场景的情况下非常有用。用它来实现带有C风格指针的数据结构是完全错误的


这里有一个具体的例子,以防上面不清楚。操作
q=newpoly()只是用新初始化的poly()替换q(堆栈上的局部变量)的内容。这更类似于清除内存,而不是分配新实例。之所以混淆是因为,在C++中,在分配时,结构和类之间没有区别。一个新的()C++总是在堆上分配。在C#中,分配位置通常由类型决定,而不是使用情况,因此当您对值类型(struct)调用new()时,这是初始化它的缩写,而不是在堆上为它分配内存


你问了一个关于“fixed”的问题,有一个很好的例子说明了为什么你不应该使用不安全的C,认为它与C基本相同。在C中,引用与指针不同。最大的区别之一是,由于C#引用是垃圾收集的,GC几乎可以在任何时候决定劫持程序的执行并替换所有引用以指向新的内存位置。如果使用通过指针引用内存的不安全代码,指针引用的对象可能会在不更新指针的情况下移动。为了解决这个问题,你可以
IntPtr newP = Marshal.AllocHGlobal(sizeof(poly));
poly* q = (poly*)newP.ToPointer();
// ......
p->link = q;