View Full Version : Does C# have pointers
Troll_King
02-17-2002, 05:08 AM
I've been reading a C# book and I'm about half way through. Things have been busy in school so I haven't been able to study C# for the last three weeks or so. Anyway, I have not reached any point in the book where I've noticed pointers in C#. Therefore are there pointers? And is it possible to impliment a linked list or any ADT? An example code would be great, but if not than fine.
Sorensen
02-17-2002, 05:43 AM
No user objects are passed by reference by default. Here's a very quick linked list (This probably doesn't represent the best way of doing it as I'm not up to full speed on C# myself) -
using System;
namespace ConsoleApplication1
{
class Node
{
public int x;
public Node next;
public Node (int _x)
{
x=_x;
}
}
class List
{
private Node head;
private Node sentinel;
public List(int x)
{
head = new Node(x);
sentinel=new Node(0);
head.next=sentinel;
}
public void Push_Back(int x)
{
Node temp = head;
while(temp.next.x!=0)
temp=temp.next;
temp.next = new Node(x);
temp.next.next=sentinel;
}
public void Print()
{
Node temp=head;
while(temp.x!=0)
{
Console.WriteLine(temp.x);
temp=temp.next;
}
}
}
class Class1
{
static void Main(string[] args)
{
List l = new List(1);
l.Push_Back(2);
l.Push_Back(3);
l.Print();
}
}
}
Troll_King
02-17-2002, 06:46 AM
I noticed something similar to this where the class name was used instead of the pointer. If objects are passed by reference as a default than maybe it makes more sense. Not used to it though.
Sorensen
02-17-2002, 06:50 AM
You can actually use pointers if you really want to, by marking code as unsafe (and setting a command line flag).
nvoigt
02-17-2002, 07:05 AM
There are two types of objects in C#: Value types and reference types. Value types are all primitive datatypes like int and double as well as all structs (!). Reference types are all classes.
Reference types are always passed by reference, while valuetypes are always passed by value. Calling a new operator and therefore constructor on a reference type creates a new object initialized by it's contructor. Calling new on a valuetype creates no new object. It just calls the contructor on the already existing object.
Example:
using System;
using System.Collections;
using System.Drawing;
namespace CProgTestCSharp
{
class Test
{
[STAThread]
static void Main(string[] args)
{
}
public void ReferenceType( Hashtable h )
{
// work with a reference ( ex-pointer )
// to a hastable. take care, maybe null
if( h == null ) return;
h.Add( "myKey", "myValue" );
}
public Point ValueType( Point p )
{
// work with a valuetype.
// Point is a struct, therefore
// never null. Changes on p have no
// effect on the parameter that
// was passed
p.X = 7;
p.Y = 5;
return p;
}
}
}
And right from the MSDN Help:
Example 1
The following example uses pointers to copy an array of bytes from src to dst.
Compile the example with the /unsafe option.
// fastcopy.cs
// compile with: /unsafe
using System;
class Test
{
// The unsafe keyword allows pointers to be used within
// the following method:
static unsafe void Copy(byte[] src, int srcIndex,
byte[] dst, int dstIndex, int count)
{
if (src == null || srcIndex < 0 ||
dst == null || dstIndex < 0 || count < 0)
{
throw new ArgumentException();
}
int srcLen = src.Length;
int dstLen = dst.Length;
if (srcLen - srcIndex < count ||
dstLen - dstIndex < count)
{
throw new ArgumentException();
}
// The following fixed statement pins the location of
// the src and dst objects in memory so that they will
// not be moved by garbage collection.
fixed (byte* pSrc = src, pDst = dst)
{
byte* ps = pSrc;
byte* pd = pDst;
// Loop over the count in blocks of 4 bytes, copying an
// integer (4 bytes) at a time:
for (int n = count >> 2; n != 0; n--)
{
*((int*)pd) = *((int*)ps);
pd += 4;
ps += 4;
}
// Complete the copy by moving any bytes that weren't
// moved in blocks of 4:
for (count &= 3; count != 0; count--)
{
*pd = *ps;
pd++;
ps++;
}
}
}
static void Main(string[] args)
{
byte[] a = new byte[100];
byte[] b = new byte[100];
for(int i=0; i<100; ++i)
a[i] = (byte)i;
Copy(a, 0, b, 0, 100);
Console.WriteLine("The first 10 elements are:");
for(int i=0; i<10; ++i)
Console.Write(b[i] + "{0}", i < 9 ? " " : "");
Console.WriteLine("\n");
}
}
Example Output
The first 10 elements are:
0 1 2 3 4 5 6 7 8 9
Code Discussion
Notice the use of the unsafe keyword, which allows pointers to be used within the Copy method.
The fixed statement is used to declare pointers to the source and destination arrays. It pins the location of the src and dst objects in memory so that they will not be moved by garbage collection. The objects will be unpinned when the fixed block completes
The reason why unsafe code is beneficial here is that it allows copying the array in chunks of 4 bytes at a time, and directly by incrementing pointers, thereby getting rid of array bounds checks and address calculations in each iteration.
Hope that satisfies your hunger for code ;)
Troll_King
02-18-2002, 05:44 AM
//c sharp version
int [] csharparray = new int [10];
for(int i =0; i < csharparray.Length; i++)
{
csharparray[i] = new int;
}
//c version
int *carray;
carray = (int *) malloc (sizeof(int) * 10);
The C# version seemed odd because it is almost as if the array is allocated once and than is allocated again for each element in the array, yet I cite a book that has an example similar to this.
nvoigt
02-18-2002, 10:12 AM
>csharparray[i] = new int;
this does not create a new int.
csharparray[i] already is an int, because integers are valuetypes.
Calling the constructor just sets it back to value zero.
For objects of referencetype ( classes ) this loop is ok, for valuetypes, it's superfluent.
C# Version:
int [] iArray = new int[10];
C++ Version:
int* iArray = new int[10];
C Version:
int* iArray = (int*)calloc( sizeof(int), 10 );
Troll_King
02-18-2002, 03:06 PM
]For objects of referencetype ( classes ) this loop is ok, for valuetypes, it's superfluent.
Okay, than say it is a class. In the book it is a class. Is it just okay than or is it a necessity to allocate space that way. First for the array as a whole, than for each element.
nvoigt
02-18-2002, 03:44 PM
For classes ( reference types in C# ) the loop is the right solution.
C# Version:
Hashtable [] hArray = new Hashtable[10];
for( int i = 0 ; i < 10 ; i++ ) hArray[i] = new Hashtable();
C++ Version:
Hashtable* hArray = new (Hashtable*)[10];
for( int i = 0 ; i < 10 ; i++ ) hArray[i] = new Hashtable();
Sorensen
02-18-2002, 03:47 PM
>Is it just okay than or is it a necessity to allocate space that way. First for the array as a whole, than for each element.
Doing it this way, it would appear so. Just doing -
myclass [] Array = new myclass[10];
doesn't call a constructor, and trying to call a myclass method without further allocation using a loop results in a NullReferenceAllocation.
Alternatively an array can be allocated like -
myclass [] Array = new myclass[2]{new myclass(),new myclass()};
or
myclass [] Array = new myclass[]{new myclass(),new myclass()};
or
myclass [] Array = {new myclass(),new myclass()};
Troll_King
02-19-2002, 01:10 AM
I mostly come from a C background and this to me looks sufficient:
myclass [] Array = new myclass[10];
That's why I asked about than having to allocate memory (or rather call the constructor) for each element. Okay, I understand this now. I was confused when I read it at first because they had one part which I suppose used a value type and another which used a reference type, and they were created differently. I was wondering which one was correct, but I guess they both were.
Unregistered
02-28-2002, 06:25 PM
Also, C# syntax looks a lot like Java's
Mr. c.
Unregistered
03-01-2002, 02:14 AM
I think it looks a little better than Java's syntax though.
vBulletin® v3.7.0, Copyright ©2000-2008, Jelsoft Enterprises Ltd.