【问题标题】:Pointers in C# to make int array?C# 中用于创建 int 数组的指针?
【发布时间】:2011-02-02 13:16:48
【问题描述】:

以下 C++ 程序按预期编译和运行:

#include <stdio.h>

int main(int argc, char* argv[])
{
    int* test = new int[10];

    for (int i = 0; i < 10; i++)
            test[i] = i * 10;

    printf("%d \n", test[5]); // 50
    printf("%d \n", 5[test]); // 50

    return getchar();
}

我可以为这个问题做的最接近的 C# 简单示例是:

using System;

class Program
{
    unsafe static int Main(string[] args)
    {
        // error CS0029: Cannot implicitly convert type 'int[]' to 'int*'
        int* test = new int[10];

        for (int i = 0; i < 10; i++)
            test[i] = i * 10;

        Console.WriteLine(test[5]); // 50
        Console.WriteLine(5[test]); // Error

        return (int)Console.ReadKey().Key;
    }
}

那么我该如何制作指针呢?

【问题讨论】:

  • 问问自己为什么要直接在托管语言中操作指针。
  • 因为我很无聊 :D
  • 在尝试用 C# 编写不安全的代码之前,请阅读规范的第 18 章(两次)来缓解您的无聊。

标签: c# c++ c pointers


【解决方案1】:

C# 不是 C++ - 不要期望在 C# 中使用与在 C++ 中相同的东西。这是一种不同的语言,在语法上有一些灵感。

在 C++ 中,数组访问是指针操作的简写。这就是为什么以下内容相同:

test[5]
*(test+5)
*(5+test)
5[test]

但是,这在 C# 中并非如此。 5[test] 不是有效的 C#,因为 System.Int32 上没有索引器属性。

在 C# 中,您很少需要处理指针。你最好直接把它当作一个 int 数组:

int[] test = new int[10];

如果您出于某种原因确实想处理指针数学,则需要标记您的方法unsafe,并将其放入fixed context。这在 C# 中并不常见,而且确实可能​​完全没有必要。

如果你真的想完成这项工作,你可以在 C# 中做的最接近的是:

using System;

class Program
{
    unsafe static int Main(string[] args)
    {
        fixed (int* test = new int[10])
        {

            for (int i = 0; i < 10; i++)
                test[i] = i * 10;

            Console.WriteLine(test[5]); // 50
            Console.WriteLine(*(5+test)); // Works with this syntax
        }

        return (int)Console.ReadKey().Key;
    }
}

(同样,这真的很奇怪 C# - 不是我推荐的......)

【讨论】:

  • 感谢您深思熟虑的答案。我只是想看看 C# 是否能够进行如此低级的内存管理。基本上你说的是那种类型的索引不能做?即使使用固定的上下文,我也无法工作。你知道我们是否完全被 Int32 卡住了,这到底是原生类型还是抽象?
  • @Joshua:我编辑了我的答案,向您展示如何实际做到这一点 - 但我真的不推荐它
  • 在 C# 运行的平台上,System.Int32 是本机 int 类型。但实际上 int[] 与您在 C++ 中看到的内存块相同。如果您执行test[5],CLR 将在后台进行边界检查,然后进行指针算术和取消引用。在这种情况下,您不会丢失任何低级操作。
  • 我同意,你必须改变你用 C# 思考和编写的方式(与 c++ 相比),尤其是指针方式。 (+1)
  • 我撤回了我的反对票。在我投票的时候,你的回答只是你的第一段,我觉得没有回答这个问题。但是您完全将答案转变为对解决方案的非常彻底的解释,并说明了为什么不应该这样做。答案应该是这样的。
【解决方案2】:

您需要使用 fixed 关键字固定数组,这样它就不会被 GC 移动:

fixed (int* test = new int[10])
{
    // ...
}

但是,C# 中的不安全代码更多是例外而不是规则。我会尝试将您的 C 代码转换为非不安全的 C# 代码。

【讨论】:

  • 注意:不要在没有充分理由的情况下使用固定变量,因为这会使 GC 的工作变得更加困难......即使你不使用所有内存(内存碎片整理)..
【解决方案3】:

您需要学习 C# 语言。尽管与 C/C++ 在语法上有相似之处,但它与 Java 一样具有非常不同的方法。

在 C# 中,默认情况下,对象表现为引用。也就是说,您不必指定指针引用 (&) 和取消引用 (*) 语法。

【讨论】:

    猜你喜欢
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 1970-01-01
    • 2014-04-30
    • 1970-01-01
    • 2010-12-10
    • 2011-09-23
    相关资源
    最近更新 更多