tags:

views:

258

answers:

3

The following C++ program compiles and runs as expected:

#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();
}

The closest C# simple example I could make for this question is:

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;
    }
}

So how do I make the pointer?

+22  A: 

C# is not C++ - don't expect the same things to work in C# that worked in C++. It's a different language, with some inspiration in the syntax.

In C++, array access is a short hand for pointer manipulation. That's why the following are the same:

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

However, this is not true in C#. 5[test] is not valid C#, since there is no indexer property on System.Int32.

In C#, you very rarely want to deal with pointers. You're better off just treating it as an int array directly:

int[] test = new int[10];

If you really do want to deal with pointer math for some reason, you need to flag your method unsafe, and put it into an fixed context. This would not be typical in C#, and is really probably something completely unnecessary.

If you really want to make this work, the closest you can do in C# would be:

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;
    }
}

(Again, this is really weird C# - not something I'd recommend...)

Reed Copsey
Thanks for the well thought out answer. I was just trying to see if C# was capable of such low level memory management. Basically what you're saying is that type of indexing cannot be done? I can't get anything to work even using the fixed context. Do you know if we are completely stuck using Int32, is that even a native type or an abstraction?
Joshua
@Joshua: I edited my answer to show you how you can actually do it - but I really don't recommend it
Reed Copsey
On the platforms C# runs on, System.Int32 is the native int type. But under the hood int[] is the same block of memory you see in C++. If you do `test[5]`, under the hood the CLR will be doing a bounds check followed by pointer arithmetic and a dereference. You're not losing any low level manipulation in this case.
Robert Davis
I agree, you must change the way you think and write in C# (compare with the c++), especial the pointer way. (+1)
Aristos
I retracted my downvote. At the time I voted, your answer was only your first paragraph which I felt did not answer the question. But you completely turned around the answer into a very thorough explanation of the solution, with a side of why it shouldn't be done. That's how answers should be.
Ricket
@Ricket: Thanks for the explanation.
Reed Copsey
+5  A: 

You need to pin the array using the fixed keyword so it won't get moved by the GC:

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

However, unsafe code in C# is more the exception than the rule. I'd try to translate your C code to non-unsafe C# code.

dtb
Note: Using fixed on variables should not be done with out a good reason as it makes the job for the GC harder... and you can run out of memory even if you don't use all the memory (memory defragmentation)..
Petoj
A: 

You need to learn the C# language. Although there are syntactic similarities to C/C++, it - like Java - has a very different approach.

In C#, objects behave, by default, as references. That is, you don't have to specify pointer referencing (&) and dereferencing (*) syntax.

Buggieboy