In C# datatype* means - c#

what exactly this means
Datatype*
Example : int*, double*, char*,...
Can any one give some explanation for it please.
Thanks in Advance.

It's an unsafe pointer. Unsafe Code Tutorial
Here is an examples using it: How to pull out alpha and count digits using regex?
private static unsafe List<long> ParseNumbers(char[] input)
{
var r = new List<long>();
fixed (char* begin = input)
{
char* it = begin, end = begin + input.Length;
while (true)
{
while (it != end && (*it < '0' || *it > '9'))
++it;
if (it == end) break;
long accum = 0;
while (it != end && *it >= '0' && *it <= '9')
accum = accum * 10 + (*(it++) - '0');
r.Add(accum);
}
}
return r;
}

Have a look at Pointer types (C# Programming Guide)
In an unsafe context, a type may be a pointer type, a value type, or a
reference type. A pointer type declaration takes one of the following
forms:
type* identifier;
void* identifier; //allowed but not recommended

Those are Pointer types.
In an unsafe context, a type may be a pointer type as well as a value type or a reference type. A pointer type declaration takes one of the following forms:
type* identifier;
void* identifier; //allowed but not recommended

They are called Pointer types
In an unsafe context, a type may be a pointer-type as well as a
value-type or a reference-type. However, a pointer-type may also be
used in a typeof expression outside of an unsafe context
as such usage is not unsafe.
A pointer-type is written as an unmanaged-type or the keyword void,
followed by a * token:
The type specified before the * in a pointer type is called the
referent type of the pointer type. It represents the type of the
variable to which a value of the pointer type points.
Unlike references (values of reference types), pointers are not
tracked by the garbage collector—the garbage collector has no
knowledge of pointers and the data to which they point. For this
reason a pointer is not permitted to point to a reference or to a
struct that contains references, and the referent type of a pointer
must be an unmanaged-type.

This is pointer in c#
please take a time to read this Unsafe Code Tutorial
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 =0 ; n < count/4 ; 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 (int n =0; n < count%4; n++)
{
*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] + " ");
Console.WriteLine("\n");
}
}
and output
The first 10 elements are:
0 1 2 3 4 5 6 7 8 9
i tooth this will give you an idea to understated pointer in c# and also how to use it
best of luck

Related

having issues when extracting char values, using unsafe char* in a struct []

in this code i am trying to simulate a task that populats an array of structs,
...unsafe to get as much throughoutput as can be achived.
the issue is that i when calling the fucntion and itterating on the result
shows different characters but within the scope of GetSomeTs() it's fine.
so just before the return i test one of the elements and it prints the correct value.
this is the testing struct.
public unsafe struct T1
{
public char* block = stackalloc char[5];<--will not compile so the process will be done within a local variable inside a method
}
public unsafe struct T1
{
public char* block;
}
static unsafe T1[] GetSomeTs(int ArrSz)
{
char[] SomeValChars = { 'a', 'b', 'c', 'd', 'e' };
T1[] RtT1Arr = new T1[ArrSz];
for (int i = 0; i < RtT1Arr.Length; i++)
{
char* tmpCap = stackalloc char[5];
for (int l = 0; l < 5; l++)
{
SomeValChars[4] = i.ToString()[0];
tmpCap[l] = SomeValChars[l];
}
RtT1Arr[i].block = tmpCap;//try 1
//arr[i].block = &tmpCap[0];//try 2
}
// here its fine
Console.WriteLine("{0}", new string(RtT1Arr[1].block));
return RtT1Arr;
}
but using it anywhere else printing garbage.
void Main()
{
T1[] tstT1 = GetSomeTs(10);
for (int i = 0; i < 10; i++)
{
Console.WriteLine("{0}", new string(tstT1[i].block));//,0,5, Encoding.Default));
}
}
When you allocate memory with stackalloc that memory only exists until the function returns in which you have allocated it. You are returning a pointer to memory that is no longer allowed to be accessed.
Hard to recommend a fix because it's unclear what you want to achieve. Probably, you should just use a managed char[].
Encoding.Default.GetBytes is pretty slow so that's likely to be your hotspot anyway and the rest is less important. i.ToString() also is quite slow and produces garbage. If you are after perf then stop creating unneeded objects all the time such as SomeValChars. Create it once and reuse.

How to use fixed with a variable of type Array or T[]?

I'm working on an IEqualityComparer which is supposed to compare arrays of primitive types really fast. My plan is to obtain pointers to the arrays and memcmp them. Like this:
public unsafe override bool Equals(T[] x, T[] y)
{
if (ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
if (x.Length != y.Length) return false;
var xArray = (Array)x;
var yArray = (Array)y;
fixed (void* xPtr = xArray) //compiler error 1
fixed (T* yPtr = y) //compiler error 2
{
return memcmp(xPtr, yPtr, x.Length * this.elementSize);
}
}
The fixed statement does not allow me to pin either Array or T[].
There error messages are:
1. Cannot implicitly convert type 'System.Array' to 'void*'
2. Cannot take the address of, get the size of, or declare a pointer to a managed type ('T')
Now, I don't actually care how I make this work (I'm not committed to this exact approach). How can I memcmp two T[] where I know that T is a primitive/blittable type?
I really want to avoid switching on the type and creating a specialized (and duplicated) code version for each interesting type. Any kind of reflection solution is not workable due to performance constraints (and yes I really need the performance here - no premature optimization warnings apply as it is customary on Stack Overflow).
where I know that T is a primitive/blittable type
You know it, the compiler doesn't know that. The CLR demands that everything in a pinned object can no longer be moved by the garbage collector. For an Array, that includes its array elements. Only kind of T that qualifies is a simple value type, one that is blittable. Generics does not give you a way to constrain T to a blittable type.
You'd normally declare the arguments of memcmp() as byte[]. The pinvoke marshaller then already does the right thing and will pin the byte[] arrays before calling memcmp(). This however will not work either since you cannot easily convert a T[] to a byte[] either. You'll have to pin yourself with GCHandle. Declare the memcmp() arguments as IntPtr instead of byte[] accordingly.
The subset of types which can work is in practice small enough to consider simply writing method overloads instead of a generic method. Which now enables the pinvoke marshaller to take care of the pinning, overload the memcmp() function declarations accordingly.
You can write a separate P/Invoke front-end for each kind of array that you want to compare. I know you don't really want to specialise on T, but the overhead isn't too great I think.
This is a bit of a hack, because I'm defining multiple P/Invoke methods with different signatures for the same API function, but by doing this I can leverage the P/Invoke marshalling support.
(Note that the sign of the return value from memcmp is really only meaningful if the source data is indeed an array of bytes. If you are giving it an array of ints, you should only compare the return value with zero and ignore its sign. The ordering that it implies is not meaningful for ints.)
For example, the following code prints the following for me (RELEASE build, not debug build):
MemCmp with ints took 00:00:08.0768666
ManagedMemCmp with ints took 00:00:10.3750453
MemCmp with bytes took 00:00:01.8740001
ManagedMemCmp with bytes took 00:00:09.2885763
Note that the byte[] test is using bytes so is comparing a quarter of the number of bytes than the int[] test uses. The managed code makes the same number of comparisons, so it is comparatively a lot slower.
There isn't really a huge difference between the times for comparing arrays of ints, but there is a large difference for comparing arrays of bytes. This suggests to me that there could be an managed optimisation that uses fixed to get a pointer to ints from a byte array in order to compare 4 bytes at a time (with some fiddling for the possibly extra bytes at the end that don't fit into an int).
I also think you could write a multithreaded managed version (using the "int*" optimisation to compare byte arrays) which would be MUCH FASTER than the unmanaged memcmp(), which is of course not multithreaded (as far as I know).
Anyway, here's my test code. Remember, RELEASE build, not debug!
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Demo
{
public static class Program
{
private static void Main(string[] args)
{
int[] a1 = new int[1000000];
int[] a2 = new int[1000000];
for (int i = 0; i < a1.Length-1; ++i)
{
a1[i] = i;
a2[i] = i;
}
a1[a1.Length-1] = 1;
a2[a1.Length-1] = 2;
byte[] b1 = new byte[1000000];
byte[] b2 = new byte[1000000];
for (int i = 0; i < b1.Length-1; ++i)
{
b1[i] = (byte)i;
b2[i] = (byte)i;
}
b1[a1.Length-1] = 1;
b2[a1.Length-1] = 2;
Stopwatch sw = Stopwatch.StartNew();
testWithMemCmp(a1, a2);
sw.Stop();
Console.WriteLine("MemCmp with ints took " + sw.Elapsed);
sw.Restart();
testWithManagedMemCmp(a1, a2);
sw.Stop();
Console.WriteLine("ManagedMemCmp with ints took " + sw.Elapsed);
sw.Restart();
testWithMemCmp(b1, b2);
sw.Stop();
Console.WriteLine("MemCmp with bytes took " + sw.Elapsed);
sw.Restart();
testWithManagedMemCmp(b1, b2);
sw.Stop();
Console.WriteLine("ManagedMemCmp with bytes took " + sw.Elapsed);
}
private static void testWithMemCmp(int[] a1, int[] a2)
{
for (int j = 0; j < COUNT; ++j)
{
MemCmp(a1, a2);
}
}
private static void testWithMemCmp(byte[] a1, byte[] a2)
{
for (int j = 0; j < COUNT; ++j)
{
MemCmp(a1, a2);
}
}
private static void testWithManagedMemCmp(int[] a1, int[] a2)
{
for (int j = 0; j < COUNT; ++j)
{
ManagedMemCmp(a1, a2);
}
}
private static void testWithManagedMemCmp(byte[] a1, byte[] a2)
{
for (int j = 0; j < COUNT; ++j)
{
ManagedMemCmp(a1, a2);
}
}
public static bool ManagedMemCmp(int[] a1, int[] a2)
{
if (a1 == null || a2 == null || a1.Length != a2.Length)
{
throw new InvalidOperationException("Arrays are null or different lengths.");
}
for (int i = 0; i < a1.Length; ++i)
{
if (a1[i] != a2[i])
{
return false;
}
}
return true;
}
public static bool ManagedMemCmp(byte[] a1, byte[] a2)
{
if (a1 == null || a2 == null || a1.Length != a2.Length)
{
throw new InvalidOperationException("Arrays are null or different lengths.");
}
for (int i = 0; i < a1.Length; ++i)
{
if (a1[i] != a2[i])
{
return false;
}
}
return true;
}
public static bool MemCmp(byte[] a1, byte[] a2)
{
if (a1 == null || a2 == null || a1.Length != a2.Length)
{
throw new InvalidOperationException("Arrays are null or different lengths.");
}
return memcmp(a1, a2, new UIntPtr((uint)a1.Length)) == 0;
}
public static bool MemCmp(int[] a1, int[] a2)
{
if (a1 == null || a2 == null || a1.Length != a2.Length)
{
throw new InvalidOperationException("Arrays are null or different lengths.");
}
return memcmp(a1, a2, new UIntPtr((uint)(a1.Length * sizeof(int)))) == 0;
}
[DllImport("msvcrt.dll")]
private static extern int memcmp(byte[] a1, byte[] a2, UIntPtr count);
[DllImport("msvcrt.dll")]
private static extern int memcmp(int[] a1, int[] a2, UIntPtr count);
private const int COUNT = 10000;
}
}
I agree with Daniel A. White's comments telling you that it probably doesn't result in a performance gain but in a performance hit because of the overhead of marshaling to unmanaged code etc.
Having said that, you should be able to use GCHandle.Alloc:
public unsafe bool Equals(T[] x, T[] y)
{
if (ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
if (x.Length != y.Length) return false;
GCHandle handleOfX = default(GCHandle);
GCHandle handleOfY = default(GCHandle);
handleOfX = GCHandle.Alloc(x, GCHandleType.Pinned);
handleOfY = GCHandle.Alloc(y, GCHandleType.Pinned);
try
{
return memcmp(handleOfX.AddrOfPinnedObject(),
handleOfY.AddrOfPinnedObject(),
x.Length * this.elementSize);
}
finally
{
if(handleOfX != default(GCHandle)) handleOfX.Free();
if(handleOfY != default(GCHandle)) handleOfY.Free();
}
}

Getting an unsafe fixed pointer to the start of a rectangular array

Consider a 2D, rectangular array. Say:
int[,] values = new int[len1, len2];
How can you iterate through all of its values in unsafe code?
The following works in an unsafe context.
fixed (int* baseOffset = values)
{
var offset = baseOffset;
var count = len1 * len2;
for (int i = 0; i < count; i++)
{
int value = *offset;
// Do whatever you need to do here
offset++;
}
}
Note that to get a pointer to the first item in an array, the types must match. So if you have a byte* which you want to treat as ushort*, you cannot cast the pointer within the fixed statement's parentheses, although you can do this within the block.

Pointers and fixed size buffers may only be used in an unsafe context

I have 2 functions within a class and getting error on the call for ParseBits() function i.e. "int num_elements = ParseBits(bits, buffer);" because of the "buffer" arguement I am passing "public int ParseBits(string bits, int* buffer)":
Function 1:
public float AssignFitness(string bits, int target_value)
{
//holds decimal values of gene sequence
int[] buffer = new int[(VM_Placement.AlgorithmParameters.chromo_length / VM_Placement.AlgorithmParameters.gene_length)];
int num_elements = ParseBits(bits, buffer);
// ok, we have a buffer filled with valid values of: operator - number - operator - number..
// now we calculate what this represents.
float result = 0.0f;
for (int i=0; i < num_elements-1; i+=2)
{
switch (buffer[i])
{
case 10:
result += buffer[i+1];
break;
case 11:
result -= buffer[i+1];
break;
case 12:
result *= buffer[i+1];
break;
case 13:
result /= buffer[i+1];
break;
}//end switch
}
// Now we calculate the fitness. First check to see if a solution has been found
// and assign an arbitarily high fitness score if this is so.
if (result == (float)target_value)
return 999.0f;
else
return 1/(float)fabs((double)(target_value - result));
// return result;
}
Function 2:
public int ParseBits(string bits, int* buffer)
{
//counter for buffer position
int cBuff = 0;
// step through bits a gene at a time until end and store decimal values
// of valid operators and numbers. Don't forget we are looking for operator -
// number - operator - number and so on... We ignore the unused genes 1111
// and 1110
//flag to determine if we are looking for an operator or a number
bool bOperator = true;
//storage for decimal value of currently tested gene
int this_gene = 0;
for (int i = 0; i < VM_Placement.AlgorithmParameters.chromo_length; i += VM_Placement.AlgorithmParameters.gene_length)
{
//convert the current gene to decimal
this_gene = BinToDec(bits.Substring(i, VM_Placement.AlgorithmParameters.gene_length));
//find a gene which represents an operator
if (bOperator)
{
if ((this_gene < 10) || (this_gene > 13))
continue;
else
{
bOperator = false;
buffer[cBuff++] = this_gene;
continue;
}
}
//find a gene which represents a number
else
{
if (this_gene > 9)
continue;
else
{
bOperator = true;
buffer[cBuff++] = this_gene;
continue;
}
}
}//next gene
// now we have to run through buffer to see if a possible divide by zero
// is included and delete it. (ie a '/' followed by a '0'). We take an easy
// way out here and just change the '/' to a '+'. This will not effect the
// evolution of the solution
for (int i = 0; i < cBuff; i++)
{
if ((buffer[i] == 13) && (buffer[i + 1] == 0))
buffer[i] = 10;
}
return cBuff;
}
I am getting 2 errors for this functions on the highlighted lines:
Error 1: The best overloaded method match for 'VM_Placement.Program.ParseBits(string, int*)' has some invalid arguments
Error 2: Pointers and fixed size buffers may only be used in an unsafe context
You need to enclose your function using raw pointers in an unsafe block.
unsafe
{
//your code
}
I had the same problem, but it wasn't solved by any of the other answers up here. I kept getting different errors.
Whatever functions use unsafe code simply need to be declared with the "unsafe" keyword.
For example:
static unsafe void myFunction(int* myInt, float* myFloat)
{
// Function definition
}
Personally, I was trying to do this when making a wrapper class.
For those interested, it ended up looking something like this:
using System.Runtime.InteropServices;
namespace myNamespace
{
public class myClass
{
[DllImport("myLib.so", EntryPoint = "myFunction")]
public static extern unsafe void myFunction(float* var1, float* var2);
}
}
Theres a lot of great information in the MSDN "Unsafe Code Tutorial":
https://msdn.microsoft.com/en-us/library/aa288474(v=vs.71).aspx
It's probably worth a read, I found it quite useful.
Perhaps I've missed it, but you don't appear to be doing anything that actually requires the use of a int*. Why not simply pass it an int array and change the ParseBits function signature to:
public int ParseBits(string bits, int[] buffer)
and remove the unsafe{ ... } blocks altogether.

Array.Reverse algorithm?

What kind of algorithm Array.Reverse(string a), uses behind the scene to reverse the string?
UPDATE: See the bottom of this answer for one truly horrifying ramification of reversing a string in-place in .NET.
"Good" Answer
In .NET, there's no Array.Reverse overload that takes a string. That said, here's how one might be implemented if it were to exist:
static string ReverseString(string str) {
char[] reversed = new char[str.Length];
for (int i = 0; i < reversed.Length; ++i)
reversed[i] = str[str.Length - 1 - i];
return new string(reversed);
}
Note that in .NET this method has to return a string, since the System.String type is immutable and so you couldn't reverse one in-place.
Scary Answer
OK, actually, it is possible to reverse a string in-place in .NET.
Here's one way, which requires compiling in unsafe mode:
static unsafe void ReverseString(string str) {
int i = 0;
int j = str.Length - 1;
fixed (char* fstr = str) {
while (i < j) {
char temp = fstr[j];
fstr[j--] = fstr[i];
fstr[i++] = temp;
}
}
}
And here's another way, which uses reflection and does not need to be compiled in unsafe mode:
static void ReverseString(string str) {
int i = 0;
int j = str.Length - 1;
// what a tricky bastard!
MethodInfo setter = typeof(string).GetMethod(
"SetChar",
BindingFlags.Instance | BindingFlags.NonPublic
);
while (i < j) {
char temp = str[j];
setter.Invoke(str, new object[] { j--, str[i] });
setter.Invoke(str, new object[] { i++, temp });
}
}
Totally inadvisable and reckless, yes -- not to mention that it would likely have horrendous performance. But possible nonetheless.
The Horror
Oh, and by the way, in case there's any doubt in your mind whatsoever that you should never do anything like this: be aware that either of the ReverseString methods I've provided above will actually allow you to write the following utterly bizarre program:
ReverseString("Hello!");
Console.WriteLine("Hello!");
The above code will output, believe it or not*:
!olleH
So yeah, unless you want all hell to break loose in your code, don't reverse a string in-place. Even though technically you can ;)
*You can try it for yourself if you don't believe me.
Probably a standard in-place reversal algorithm.
function reverse-in-place(a[0..n])
for i from 0 to floor(n/2)
swap(a[i], a[n-i])
Sources
Wikipedia/In-place algorithm
The algorithm is probably using two pointers i and j that start at 0 and length-1 respectively. Then the characters at position i and j are swapped (with the help of a temporal variable) and i is incremented and j decremented by 1. These steps are repeated until both pointers reach each other (i ≥ j).
In pseudo-code:
i := 0;
j := a.length-1;
while (i < j) do
tmp := a[i];
a[i] := a[j];
a[j] := tmp;
i := i+1;
j := j-1;
endwhile;
According to Reflector, Array.Reverse(Array) (there's no string variation) first calls something called TrySZReverse, for which I can't find the implementation. I assume it's some sort of heavily optimized native method..
If that fails, it does something like this:
int num = index;
int num2 = (index + length) - 1;
while (num < num2)
{
object obj2 = objArray[num];
objArray[num] = objArray[num2];
objArray[num2] = obj2;
num++;
num2--;
}
So, an in place algorithm, where it swaps the values at each end, then moves inward, repeatedly.
Here's a general-purpose, language-independent, question-appropriate answer: It copies the input string to the output string, reading from one end and writing to the other.
My suggestion:
private string Reverse(string text)
{
char[] c = text.ToCharArray(0, text.Length);
Array.Reverse(c);
return new string(c);
}

Categories

Resources