1

I'm sorry if this has been asked before, but I don't even know what to search for to find an answer.

I'm fairly experienced in .net/c# etc., however, I have come across something I don't understand how works.

I'm working on a third party library where I do not have access to the source.

My question is: How is this function able to get the whole data in the array when only the first value is being passed?

Prototype:

SomeClass(ref byte pByte, int length);

Code example:

...
byte[] bArr = new byte[100];
// fill array with some data
SomeClass(ref bArr[0], bArr.Length);
...

Update: Sorry I didn't include this in the post to begin with. I am en experienced embedded fw engineer but I have also worked with c#/.net/wpf/wcf etc. for many years. So I am well aware of the difference between pass-by-value/reference and the ref modifier. My initial confusion was that I have never seen any c# function calls only passing the first element in an array (like pointers in c/c++) and the function can access the whole array. So it's more the syntax that got me. :)

Thanks to @jdweng's comment I used iLSpy to confirm Nicholas Carey's answer. The library is just a CLR wrapped c++ library where the dll importing and marshaling is done.

Thank you all for your answers. :)

5
  • There are two way of passing values 1) By Value 2) By Reference "By Value" the entire array is passed to method not just first location. "By Reference" an address is passed where first location is found. Not the value of the first location. Commented Feb 1, 2022 at 17:34
  • 2
    I'm working on a third party library where I do not have access to the source. - allow me to introduce you to ILSpy.. Commented Feb 1, 2022 at 17:41
  • Have a read of stackoverflow.com/questions/29201846/… Commented Feb 1, 2022 at 17:43
  • Arrays in .net are objects derived from System.Array. Given that, a parameter like byte[] bytes is also a reference. What the ref variable introduces is the ability to make the reference point to a different object. Commented Feb 1, 2022 at 18:03
  • @andidegn about the update part: is not limited to c++ thought, I've added the c# version. Commented Feb 1, 2022 at 21:34

3 Answers 3

1

An array is a contiguous bit of memory, calling a function like this:

foo( ref bAarr[0], bArr.Length );

It passes two things:

  • The address of the 1st element of the array, and
  • The number of elements in the array

Your 3rd-party library is almost certainly a C/C++ DLL exposing a function signature along the lines of

int foo( unsigned char *p, int len );

An array reference like arr[n] is [roughly] the equivalent of the following pseudocode:

  • let p be the address of arr
  • let offset be n multiplied by the size in octets of the array's underlying type
  • let pElement be p + offset, the address of element n of array arr.

pElement, when dereferenced, gives you the value of arr[n].

Sign up to request clarification or add additional context in comments.

Comments

0

@Nicholas explained how it happens but if you want to do the same thing in the c# check the bellow code:

I don't recommend using it, just for satisfying curiosity:

void Main()
{
    byte[] bArr = new byte[100];

    // fill the entire array without passing it to method
    FillEntireArray(ref bArr[0], bArr.Length);
    
    // read the entire array without passing it to method
    ReadEntireArray(ref bArr[0], bArr.Length);
}

public unsafe void FillEntireArray(ref byte pByte, int length)
{
    fixed (byte* ptr = &pByte)
    {
        byte* p = ptr;
        for (int i = 0; i < length; i++)
        {
            // set a new value to pointer
            *p = ((byte)(i));

            // move pointer to next item
            p++;
        }
    }
}

public unsafe void ReadEntireArray(ref byte pByte, int length)
{
    fixed (byte* ptr = &pByte)
    {
        byte* p = ptr;
        for (int i = 0; i < length; i++)
        {
            // Print the value of *p:
            Console.WriteLine($"Value at address 0x{(int)p:X} is {p->ToString()}");

            // move pointer to next item
            p++;
        }
    }
}

Comments

0

shorter form:

public unsafe void FillArray(ref byte arr, int length)
{
    fixed (byte* ptr = &arr)
    {
        for (byte i = 0; i<length; i++)
        {
            *(ptr + i) = i;
        }
    }
}

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.