-1

I have:

        List<double> w = new List<double>();
        w.Add(1);
        w.Add(2);
        w.Add(1);
        w.Add(4);
        w.Add(5);
        w.Add(1);
        foreach (double num in w)
        {
           Console.WriteLine(num);
        }

Which writes

1 2 1 4 5 1

How do I print the memory location of each number, I tried &num, but get error.

edgarmtze
  • 24,683
  • 80
  • 235
  • 386
  • 3
    Isn't that partly the point of c# - you're not supposed to bother with the actual memory addresses since memory management is largely handled for you? Is there a specific reason you need the addresses? – Adam V Aug 05 '11 at 15:35
  • possible duplicate of [C# memory address and variable](http://stackoverflow.com/questions/588817/c-memory-address-and-variable) – Davide Piras Aug 05 '11 at 15:36
  • well, I need to do some contiguos memory passing, and tell some other function where to start pointing – edgarmtze Aug 05 '11 at 15:36
  • http://msdn.microsoft.com/en-us/library/y31yhkeb%28v=vs.80%29.aspx – Nate C-K Aug 05 '11 at 15:39
  • @cMinor If this is for interops then you should marshal the array / items instead of using `unsafe`. – Justin Aug 05 '11 at 15:39
  • @cMinor: you don't do it that way in C#. If you need to pass a contiguous block of doubles to unmanaged code, allocate an array and pass it. p/invoke marshaler will pin the array in memory for the duration of the call, take its address and pass it. – Anton Tykhyy Aug 05 '11 at 15:42
  • could you please post any example of `p/invoke marshaler` – edgarmtze Aug 05 '11 at 15:43
  • @cMinor - can you give some more information on what you're trying to achieve so we can give you a relevant example. – Mark H Aug 05 '11 at 15:47
  • I want to pass the initial memory of the list to some function (if it were an array I would pass it `&array[0]`), so thats why I need the adress of the first element of the list... – edgarmtze Aug 05 '11 at 15:49
  • cMinor - There is tons of information on this website. How about comming back when you got a specfic question. You should not go about what you want to do it, per your question, think of a new question and asked that. – Security Hound Aug 05 '11 at 16:15

4 Answers4

1

There is now way to get a memory location in c#. Memory addresses are tabu in the .NET Framework, because the garbage collector may rearrange the stuff on the heap.

All you can use in your case is the list index. You could reformulate your loop like:

for (i = 0; i < w.Count; i++) {
    Console.WriteLine(w[i]);
}

If you would like to reference an item directly, then use a reference type like:

class MyDouble
{
    Public double Num { get; set; }
}

And then declare:

var w = new List<MyDouble>();
w.Add(new MyDouble{Num = 1});
var referenced = new MyDouble{Num = 2};
w.Add(referenced);
a.Add(...);
Console.WriteLine(referenced.Num);
referenced.Num = 7;
1

There is yet another reason why not to use a memory location. If you add items to the list, the internal array used to store the list items might be resized, i.e. a new array having the double size of the previous one will be created and the items will be copied into the new array. The reference trick shown in my last post, however, would still work.

1

If you're using P/Invoke and you want to pass a list of elements to a C function, you can use attributes in most cases to have the work done for you. Eg.

[DllImport("x.dll")]
extern void PassDoubleArray([MarshalAs(UnmanagedType.LPArray)]Double[] array);

If you have something a bit more complex and need to do it manually, the Marshal class has most of what you need to get it done.

First, allocate some unmanaged memory - enough to store your object or array, using Marshal.AllocHGlobal, which will give you an IntPtr. You can copy .NET primitives to and from the unmanaged memory by using Marshal.Copy. For non primitives, create structs and use Marshal.StructureToPtr to get an IntPtr for it. When you're done with the unmanaged memory, make a call to Marshal.FreeHGlobal to free it up.

eg, this will do the equivalent of the above attribute, but more long-winded.

[DllImport("x.dll")]
extern void PassDoubleArray(IntPtr array);

List<Double> vals = new List<Double>() { ... }
IntPtr unmanaged = Marshal.AllocHGlobal(vals.Length * sizeof(Double));
Marshal.Copy(vals.ToArray(), 0, unmanaged, vals.Length);
PassDoubleArray(unmanaged);
Marshal.FreeHGlobal(unmanaged);
Mark H
  • 13,797
  • 4
  • 31
  • 45
0

You'll have to use unsafe code in order for this to work. See here for more details.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315