Are ref and out in C# the same a pointers in C++? - c#

I just made a Swap routine in C# like this:
static void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
It does the same thing that this C++ code does:
void swap(int *d1, int *d2)
{
int temp=*d1;
*d1=*d2;
*d2=temp;
}
So are the ref and out keywords like pointers for C# without using unsafe code?

They're more limited. You can say ++ on a pointer, but not on a ref or out.
EDIT Some confusion in the comments, so to be absolutely clear: the point here is to compare with the capabilities of pointers. You can't perform the same operation as ptr++ on a ref/out, i.e. make it address an adjacent location in memory. It's true (but irrelevant here) that you can perform the equivalent of (*ptr)++, but that would be to compare it with the capabilities of values, not pointers.
It's a safe bet that they are internally just pointers, because the stack doesn't get moved and C# is carefully organised so that ref and out always refer to an active region of the stack.
EDIT To be absolutely clear again (if it wasn't already clear from the example below), the point here is not that ref/out can only point to the stack. It's that when it points to the stack, it is guaranteed by the language rules not to become a dangling pointer. This guarantee is necessary (and relevant/interesting here) because the stack just discards information in accordance with method call exits, with no checks to ensure that any referrers still exist.
Conversely when ref/out refers to objects in the GC heap it's no surprise that those objects are able to be kept alive as long as necessary: the GC heap is designed precisely for the purpose of retaining objects for any length of time required by their referrers, and provides pinning (see example below) to support situations where the object must not be moved by GC compacting.
If you ever play with interop in unsafe code, you will find that ref is very closely related to pointers. For example, if a COM interface is declared like this:
HRESULT Write(BYTE *pBuffer, UINT size);
The interop assembly will turn it into this:
void Write(ref byte pBuffer, uint size);
And you can do this to call it (I believe the COM interop stuff takes care of pinning the array):
byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);
In other words, ref to the first byte gets you access to all of it; it's apparently a pointer to the first byte.

Reference parameters in C# can be used to replace one use of pointers, yes. But not all.
Another common use for pointers is as a means for iterating over an array. Out/ref parameters can not do that, so no, they are not "the same as pointers".

ref and out are only used with function arguments to signify that the argument is to be passed by reference instead of value. In this sense, yes, they are somewhat like pointers in C++ (more like references actually). Read more about it in this article.

The nice thing about using out is that you're guaranteed that the item will be assigned a value -- you will get a compile error if not.

Actually, I'd compare them to C++ references rather than pointers. Pointers, in C++ and C, are a more general concept, and references will do what you want.
All of these are undoubtedly pointers under the covers, of course.

While comparisons are in the eye of the beholder...I say no. 'ref' changes the calling convention but not the type of the parameters. In your C++ example, d1 and d2 are of type int*. In C# they are still Int32's, they just happen to be passed by reference instead of by value.
By the way, your C++ code doesn't really swap its inputs in the traditional sense. Generalizing it like so:
template<typename T>
void swap(T *d1, T *d2)
{
T temp = *d1;
*d1 = *d2;
*d2 = temp;
}
...won't work unless all types T have copy constructors, and even then will be much more inefficient than swapping pointers.

The short answer is Yes (similar functionality, but not exactly the same mechanism).
As a side note, if you use FxCop to analyse your code, using out and ref will result in a "Microsoft.Design" error of "CA1045:DoNotPassTypesByReference."

Related

Is it possible to create a 6400 byte integer?

I have a function which I can't alter because of protection and abstraction, and it is declared like this:
GetDeviceLongInfo(int, int, ref int);
In which the "ref int" argument to be passed is said to give back 6400 bytes of information.
My question is, how can I get this information in a variable if the only choice I have is to give the function an Int32? Can I allocate more memory for that Int32? Is this even possible to achieve in some way?
EDIT:
I can tell you that the function uses the ref int to dump values in it, the int size (size of the information) is not fixed, depends on the option chosed in the second parameter. I can't even look at the function to see how it uses that ref.
You can allocate an int[] and pass that to the function. This is a hack but I don't see why it should not be safe.
var array = new int[6400 / sizeof(int)];
GetDevice(..., ref array[0]);
The array is pinned by the CLR for the duration of the call.
Note, that ref is a so called managed pointer to the CLR. It is marshaled by passing it as a pointer and pinning the object it points to. An int[] would be passed in almost the same way (a pointer to the first element is passed).
Can I allocate more memory for that Int32? No
Is this even possible to achieve in some way? Changing the signature or using the int as a reference to the data are both options
You're attempting to marshal an array (which is a native pointer to data) to an integer. C# will have no problem with that, but processing it is another story. Also note that depending on your architecture you will have different pointer sizes, which means using a 32-bit int isn't the way to go.
See also: http://msdn.microsoft.com/en-us/library/z6cfh6e6(v=vs.110).aspx
I cannot remember the details from the top of my head, but basically you want to use the MarshalAs to tell .NET that it's a pointer to an array. IIRC it was something like this (1600 = 6400/4):
void GetDeviceLongInfo(int, int, [MarshalAs(UnmanagedType.LPArray, SizeConst=1600)] int[] ar );
update
I noticed the questions on how this works, so here it is... How this signature will work: signature in C is probably (long, long, long*) which means the third argument should be a pointer to int. The underlying buffer will be filled with the GetDeviceLongInfo by means of a strncpy or something similar. Things that can go wrong is passing a buffer that's too small (that's checked running it in Debug mode in VS), using the wrong processor architecture, incorrectly passing the integer instead of a pointer (you can try casting the address of your AllocHGlobal to int and see if that works -- that does mean you will have to run on x86 though) and basically a whole lot of other things :-)
Apparently you cannot change anything to the signature. What you're basically attempting to do then is allocate a buffer, cast it to an int* and then process it. Since the approach of usr isn't working, I'd try Marshal.AllocHGlobal to create the buffer, and then pass it to the function (if needed, use unsafe code).

Use the ref and out keyword on a pointer parameter

I'm learning C and C#, this question is for C#. Why would you ever use the out and ref keywords on pointers? With pointers you have direct access to the variable. I found this code on msdn:here.
Here is the code:
static int value = 20;
public unsafe static void F(out int* pi1, ref int* pi2)
{
int i = 10;
pi1 = &i;
fixed (int* pj = &value)
{
// ...
pi2 = pj;
}
}
Why would you ever use the out and ref keywords on pointers?
Well, why would you ever use the out and ref keywords, period? You use the out keyword when you wish to call a method that modifies an existing variable. You use the ref keyword when you wish to call a method that reads and modifies an existing variable. That the variables are of pointer type seems to not be particularly relevant.
If your question is in fact "can you give me an example of realistic code in which you might want to pass a pointer-typed variable by ref?" then I must confess that in ten years of writing C# code I have never used pointers in production code and very rarely use ref, so I don't have an example from personal experience. I can imagine such a thing though. For example, imagine a traditional C-style doubly-linked list. You might have a situation where you want to both read and mutate the head and tail pointers of the list, and do so by passing ref Link*s to the head and tail.
Now that you have included the link to where you found this code I note that it explicitly says that this is an example of dangerously broken code that you must never write. Asking under what circumstances you would want to write such code is therefore a non-starter. I really don't understand the point of your question now that I see the origin of the code; you should never write code like this; that's the whole point of the sample.
Why would you ever use the out and ref keywords on pointers?
When you want to provide a pointer to the caller of your function, in the case of out, or when you want to be given a pointer and optionally modify it to point to something different, in the case of ref.
If you don't need to mutate the pointer, and instead only need to dereference the pointer to see what it is pointing to, then you can pass the pointer by value, rather than by reference, which is the behavior whenever out and ref are not used.
I've never used pointers in C#, but I do use ref parameters with reference types. Reason: clear intentions. If I see a method that takes a ref parameter, I know that this parameter will be mutated, so no surprises there.

Is it safe to keep C++ pointers in C#?

I'm currently working on some C#/C++ code which makes use of invoke. In the C++ side there is a std::vector full of pointers each identified by index from the C# code, for example a function declaration would look like this:
void SetName(char* name, int idx)
But now I'm thinking, since I'm working with pointers couldn't I sent to C# the pointer address itself then in code I could do something like this:
void SetName(char*name, int ptr)
{
((TypeName*)ptr)->name = name;
}
Obviously that's a quick version of what I'm getting at (and probably won't compile).
Would the pointer address be guaranteed to stay constant in C++ such that I can safely store its address in C# or would this be too unstable or dangerous for some reason?
In C#, you don't need to use a pointer here, you can just use a plain C# string.
[DllImport(...)]
extern void SetName(string name, int id);
This works because the default behavior of strings in p/invoke is to use MarshalAs(UnmanagedType.LPStr), which converts to a C-style char*. You can mark each argument in the C# declaration explicitly if it requires some other way of being marshalled, eg, [MarshalAs(UnmanagedType.LPWStr)], for an arg that uses a 2-byte per character string.
The only reason to use pointers is if you need to retain access to the data pointed to after you've called the function. Even then, you can use out parameters most of the time.
You can p/invoke basically anything without requiring pointers at all (and thus without requiring unsafe code, which requires privileged execution in some environments).
Yes, no problem. Native memory allocations never move so storing the pointer in an IntPtr on the C# side is fine. You need some kind of pinvoked function that returns this pointer, then
[DllImport("something.dll", CharSet = CharSet.Ansi)]
void SetName(IntPtr vector, string name, int index);
Which intentionally lies about this C++ function:
void SetName(std::vector<std::string>* vect, const char* name, int index) {
std::string copy = name;
(*vect)[index] = copy;
}
Note the usage of new in the C++ code, you have to copy the string. The passed name argument points to a buffer allocated by the pinvoke marshaller and is only valid for the duration of the function body. Your original code cannot work. If you intend to return pointers to vector<> elements then be very careful. A vector re-allocates its internal array when you add elements. Such a returned pointer will then become invalid and you'll corrupt the heap when you use it later. The exact same thing happens with a C# List<> but without the risk of dangling pointers.
I think it's stable till you command C++ code and perfectly aware what he does, and other developers that work on the same code know about that danger too.
So by my opinion, it's not very secure way of architecture, and I would avoid it as much as I can.
Regards.
The C# GC moves things, but the C++ heap does not move anything- a pointer to an allocated object is guaranteed to remain valid until you delete it. The best architecture for this situation is just to send the pointer to C# as an IntPtr and then take it back in C++.
It's certainly a vastly, incredibly better idea than the incredibly BAD, HORRIFIC integer cast you've got going there.

C++ to C# port question: How would I deal with a method that has a double* as a parameter?

I'm porting a C++ library to C# and I've encountered some methods that have double* pointers as parameters. What's the best way to deal with this? Perhaps modify the calling code so that it's not passing pointers? I WOULD just wrap the code in an "unsafe" block and set the compiler's /unsafe flag, but I can't do that inside of the method signature.
Maybe uusing ref (or out) on parameters may be good enough, or if you need to handle an array of those use a double[].
Maybe post the method definition so that it gets clearer what you really need.
I'm assuming that you wish to use managed safe code
Depends on how the pointer is used. If it's used as an array inside your method then you'll need to pass an array to the method and therefor need to change the signature.
if it's used as a double and (re)assigned it again depends. Does the method have return type? if so using ref double might be the way to go. if the method doesn't have a return type return the value being assigned and let the caller passing to a local instead of passing by ref.
if the double* is used as a double and never assign simply pass as double.
Probably it translates to ref double or out double or double[]. Which it should be depends on the semantics of the code. C++ double* can actually mean a number of things.
It's highly unlikely that unsafe code is needed.
You could mark the function as unsafe and compile with the /unsafe flag:
private static unsafe void MyFunction(double *d)
See http://msdn.microsoft.com/en-us/library/chfa2zb8.aspx
Where you are passing pointers, you are simply changing the default pass-by-value mechanism to pass-by-reference, in which case, use the ref keyword:
public void SomeMethod(ref double val) { }
In which you need to ensure you specifiy ref when call it too:
SomeMethod(ref 12.0);
What you do will depend on how the pointer is being used. If the pointer is there so that the calling code can pass an array of doubles, then have the method accept a double[]. If the pointer is there so that the called code can modify the value of a double variable from the caller, then you have two choices:
Modify the semantics of the call in such a way that the double is a return value (this would be the way I'd suggest)
Declare the parameter as ref or out (depending on whether or not you want to guarantee that the called function will assign a value.
Don't just throw unsafe blocks around code so that you can continue to use pointers; unsafe should be used very sparingly (ideally not at all).
It depends on how the function uses the pointer. You don't really give enough info to give a solid answer, but I'll give it a shot anyway.
Normal C# code
If the code in the method is de-referencing the pointer and assigning a value, without doing any pointer arithmetic, then simply make the parameter an out parameter.
If the previous paragraph is true, and you don't already have a return value, simply modify the signature of the method to return a double.
If the code is not doing pointer arithmetic, but uses the value that already exists at the pointed location, as well as assigning it, then make the parameter a ref parameter.
If the code does no pointer arithmetic, uses the value, but doesn't assign it, then you should probably change it from a pointer to a plain double, and not make it ref or out.
If the implementation of the function is doing pointer arithmetic, then you'll need to build and pass some sort of indexable collection, such as one that implements IList or an array.
Alternatives to normal C# code
You could always opt to mark your code unsafe, too, and use pointers. That will probably be a lot more work than simple logical translations, but is more likely to maintain a similar performance profile.
You could also opt to use C++/CLI instead of C#. It is also a .Net langauge, and might be simpler (depending on your app) to integrate directly with the existing C++ code.

How do you explain C++ pointers to a C#/Java developer? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am a C#/Java developer trying to learn C++. As I try to learn the concept of pointers, I am struck with the thought that I must have dealt with this concept before. How can pointers be explained using only concepts that are familiar to a .NET or Java developer? Have I really never dealt with this, is it just hidden to me, or do I use it all the time without calling it that?
Java objects in C++
A Java object is the equivalent of a C++ shared pointer.
A C++ pointer is like a Java object without the garbage collection built in.
C++ objects.
C++ has three ways of allocating objects:
Static Storage Duration objects.
These are created at startup (before main) and die after main exits.
There are some technical caveats to that but that is the basics.
Automatic Storage Duration objects.
These are created when declared and destroyed when they go out of scope.
I believe these are like C# structs
Dynamic Storage Duration objects
These are created via new and the closest to a C#/Java object (AKA pointers)
Technically pointers need to be destroyed manually via delete. But this is considered bad practice and under normal situations they are put inside Automatic Storage Duration Objects (usually called smart pointers) that control their lifespan. When the smart pointer goes out of scope it is destroyed and its destructor can call delete on the pointer. Smart pointers can be though of as fine grain garbage collectors.
The closest to Java is the shared_ptr, this is a smart pointer that keeps a count of the number of users of the pointer and deletes it when nobody is using it.
You are "using pointers" all the time in C#, it's just hidden from you.
The best way I reckon to approach the problem is to think about the way a computer works. Forget all of the fancy stuff of .NET: you have the memory, which just holds byte values, and the processor, which just does things to these byte values.
The value of a given variable is stored in memory, so is associated with a memory address. Rather than having to use the memory address all the time, the compiler lets you read from it and write to it using a name.
Furthermore, you can choose to interpret a value as a memory address at which you wish to find another value. This is a pointer.
For example, lets say our memory contains the following values:
Address [0] [1] [2] [3] [4] [5] [6] [7]
Data 5 3 1 8 2 7 9 4
Let's define a variable, x, which the compiler has chosen to put at address 2. It can be seen that the value of x is 1.
Let's now define a pointer, p which the compiler has chosen to put at address 7. The value of p is 4. The value pointed to by p is the value at address 4, which is the value 2. Getting at the value is called dereferencing.
An important concept to note is that there is no such thing as a type as far as memory is concerned: there are just byte values. You can choose to interpret these byte values however you like. For example, dereferencing a char pointer will just get 1 byte representing an ASCII code, but dereferencing an int pointer may get 4 bytes making up a 32 bit value.
Looking at another example, you can create a string in C with the following code:
char *str = "hello, world!";
What that does is says the following:
Put aside some bytes in our stack frame for a variable, which we'll call str.
This variable will hold a memory address, which we wish to interpret as a character.
Copy the address of the first character of the string into the variable.
(The string "hello, world!" will be stored in the executable file and hence will be loaded into memory when the program loads)
If you were to look at the value of str you'd get an integer value which represents an address of the first character of the string. However, if we dereference the pointer (that is, look at what it's pointing to) we'll get the letter 'h'.
If you increment the pointer, str++;, it will now point to the next character. Note that pointer arithmetic is scaled. That means that when you do arithmetic on a pointer, the effect is multiplied by the size of the type it thinks it's pointing at. So assuming int is 4 bytes wide on your system, the following code will actually add 4 to the pointer:
int *ptr = get_me_an_int_ptr();
ptr++;
If you end up going past the end of the string, there's no telling what you'll be pointing at; but your program will still dutifully attempt to interpret it as a character, even if the value was actually supposed to represent an integer for example. You may well be trying to access memory which is not allocated to your program however, and your program will be killed by the operating system.
A final useful tip: arrays and pointer arithmetic are the same thing, it's just syntactic sugar. If you have a variable, char *array, then
array[5]
is completely equivalent to
*(array + 5)
A pointer is the address of an object.
Well, technically a pointer value is the address of an object. A pointer object is an object (variable, call it what you prefer) capable of storing a pointer value, just as an int object is an object capable of storing an integer value.
["Object" in C++ includes instances of class types, and also of built-in types (and arrays, etc). An int variable is an object in C++, if you don't like that then tough luck, because you have to live with it ;-)]
Pointers also have static type, telling the programmer and the compiler what type of object it's the address of.
What's an address? It's one of those 0x-things with numbers and letters it it that you might sometimes have seen in a debugger. For most architectures we can consider memory (RAM, to over-simplify) as a big sequence of bytes. An object is stored in a region of memory. The address of an object is the index of the first byte occupied by that object. So if you have the address, the hardware can get at whatever's stored in the object.
The consequences of using pointers are in some ways the same as the consequences of using references in Java and C# - you're referring to an object indirectly. So you can copy a pointer value around between function calls without having to copy the whole object. You can change an object via one pointer, and other bits of code with pointers to the same object will see the changes. Sharing immutable objects can save memory compared with lots of different objects all having their own copy of the same data that they all need.
C++ also has something it calls "references", which share these properties to do with indirection but are not the same as references in Java. Nor are they the same as pointers in C++ (that's another question).
"I am struck with the thought that I must have dealt with this concept before"
Not necessarily. Languages may be functionally equivalent, in the sense that they all compute the same functions as a Turing machine can compute, but that doesn't mean that every worthwhile concept in programming is explicitly present in every language.
If you wanted to simulate the C memory model in Java or C#, though, I suppose you'd create a very large array of bytes. Pointers would be indexes in the array. Loading an int from a pointer would involve taking 4 bytes starting at that index, and multiplying them by successive powers of 256 to get the total (as happens when you deserialize an int from a bytestream in Java). If that sounds like a ridiculous thing to do, then it's because you haven't dealt with the concept before, but nevertheless it's what your hardware has been doing all along in response to your Java and C# code[*]. If you didn't notice it, then it's because those languages did a good job of creating other abstractions for you to use instead.
Literally the closest the Java language comes to the "address of an object" is that the default hashCode in java.lang.Object is, according to the docs, "typically implemented by converting the internal address of the object into an integer". But in Java, you can't use an object's hashcode to access the object. You certainly can't add or subtract a small number to a hashcode in order to access memory within or in the vicinity of the original object. You can't make mistakes in which you think that your pointer refers to the object you intend it to, but actually it refers to some completely unrelated memory location whose value you're about to scribble all over. In C++ you can do all those things.
[*] well, not multiplying and adding 4 bytes to get an int, not even shifting and ORing, but "loading" an int from 4 bytes of memory.
References in C# act the same way as pointers in C++, without all the messy syntax.
Consider the following C# code:
public class A
{
public int x;
}
public void AnotherFunc(A a)
{
a.x = 2;
}
public void SomeFunc()
{
A a = new A();
a.x = 1;
AnotherFunc(a);
// a.x is now 2
}
Since classes are references types, we know that we are passing an existing instance of A to AnotherFunc (unlike value types, which are copied).
In C++, we use pointers to make this explicit:
class A
{
public:
int x;
};
void AnotherFunc(A* a) // notice we are pointing to an existing instance of A
{
a->x = 2;
}
void SomeFunc()
{
A a;
a.x = 1;
AnotherFunc(&a);
// a.x is now 2
}
"How can pointers be explained using only concepts that are familiar to a .NET or Java developer? "
I'd suggest that there are really two distinct things that need to be learnt.
The first is how to use pointers, and heap allocated memory, to solve specific problems. With an appropriate style, using shared_ptr<> for example, this can be done in a manner analogous to that of Java. A shared_ptr<> has a lot in common with a Java object handle.
Secondly, however, I would suggest that pointers in general are a fundamentally lower level concept that Java, and to a lesser extent C#, deliberately hides. To program in C++ without moving to that level will guarantee a host of problems. You need to think in terms of the underlying memory layout and think of pointers as literally pointers to specific pieces of storage.
To attempt to understand this lower level in terms of higher concepts would be an odd path to take.
Get two sheets of large format graph paper, some scissors and a friend to help you.
Each square on the sheets of paper represents one byte.
One sheet is the stack.
The other sheet is the heap. Give the heap to your friend - he is the memory manager.
You are going to pretend to be a C program and you'll need some memory. When running your program, cut out chunks from the stack and the heap to represent memory allocation.
Ready?
void main() {
int a; /* Take four bytes from the stack. */
int *b = malloc(sizeof(int)); /* Take four bytes from the heap. */
a = 1; /* Write on your first little bit of graph paper, WRITE IT! */
*b = 2; /* Get writing (on the other bit of paper) */
b = malloc(sizeof(int)); /* Take another four bytes from the heap.
Throw the first 'b' away. Do NOT give it
back to your friend */
free(b); /* Give the four bytes back to your friend */
*b = 3; /* Your friend must now kill you and bury the body */
} /* Give back the four bytes that were 'a' */
Try with some more complex programs.
Explain the difference between the stack and the heap and where objects go.
Value types such as structs (both C++ and C#) go on the stack. Reference types (class instances) get put on the heap. A pointer (or reference) points to the memory location on the heap for that specific instance.
Reference type is the key word. Using a pointer in C++ is like using ref keyword in C#.
Managed apps make working with this stuff easy so .NET devs are spared the hassle and confusion. Glad I don't do C anymore.
The key for me was to understand the way memory works. Variables are stored in memory. The places in which you can put variables in memory are numbered. A pointer is a variable that holds this number.
Any C# programmer that understands the semantic differences between classes and structs should be able to understand pointers. I.e., explaining in terms of value vs. reference semantics (in .NET terms) should get the point across; I wouldn't complicate things by trying to explain in terms of ref (or out).
In C#, all references to classes are roughly the equivalent to pointers in the C++ world. For value types (structs, ints, etc..) this is not the case.
C#:
void func1(string parameter)
void func2(int parameter)
C++:
void func1(string* parameter)
void func2(int parameter)
Passing a parameter using the ref keyword in C# is equivalent to passing a parameter by reference in C++.
C#:
void func1(ref string parameter)
void func2(ref int parameter)
C++:
void func1((string*)& parameter)
void func2(int& parameter)
If the parameter is a class, it would be like passing a pointer by reference.

Categories