How to pass a pointer to function in c/cpp? - c++

I want to pass a pointer to a function.
Lets say I am creating a structure and declare a pointer to that structure. I allocate memory to that pointer and then I want to "pass" that pointer to a function so I can do stuff to that block of memory. How I do that?

It is done the same way as passing a normal variable. You shouldn't think of a pointer any different than a variable, as a pointer is a variable (although a bit special).
Say you have an integer and a pointer to that integer:
int a = 0;
int * ptr = &a;
Note that ptr and a are both variables, and in this instance, we use the reference operator & to reference a by &a which gives the address of a -- this is a pointer to a.
Now say you have two functions:
void foo(int i){}
void bar(int * p){}
Now these two functions do the same thing (nothing), but one takes an int and one takes a pointer to an int, int *. If you called foo(a) and modified i, i would be modified in the function body, but have no effect on a. If you called bar(ptr) and modified the value pointed to by ptr by using the dereference operator * as something like *ptr = 1, it would modify the value pointed to by ptr, which in this case would be a.
In your case, passing a struct would be just the same. Say you have a structure
struct MyStruct { int b; };
And had two more functions
void structFoo(struct MyStruct m) {}
void structBar(struct MyStruct * mp) {}
You could work on the pointer in the same way as our above int and int * functions, although you would now also have to access the struct components by dereferencing the struct with (*mp).b, or the shorthand version mp->b.
For ease of use, you may also want to do something like
typedef struct MyStruct MyStruct;
Which will allow you to use MyStruct as the type name rather than requiring struct MyStruct as in the above functions, although you may want to avoid doing this until you fully understand what is happening and get through difficulties with pointers.
Hopefully that gives you some idea of what is going on, although the C++ tutorial on pointers gives a much more in-depth discussion than what I can provide.
It would be a good exercise to create some small programs and mess around with pointer and regular types while printing the results to help understand what is happening where. You should remember that to allocate a pointer, you're going to need to use either new or malloc(), otherwise you will have a SEGFAULT error. This is not an issue when referencing a variable declared as I have done with &a above as the memory is already allocated when a declaration such as int a is made. A declaration of a pointer allocates the memory for that pointer, but not the memory that it points to. This eventually leads into the difference between the stack and the heap, although I wouldn't think about that until you have a very thorough understanding of pointers.

Structure in c/cpp is like all the other types. You can use & and * as you do it for int.

Related

How to use unique_ptr with data allocated within a c library?

I'm in c++ and i'm writing a wrapper around a c library. The c library function i'm working with takes a type 'LDAPMessage **' as a parameter, where it will allocate the memory for you within the function. Normal usage looks like this:
LDAPMessage * msg;
c_lib_function(&msg); // allocates the memory for me
Now I want to use unique_ptr in this case, with a custom deleter. Assume my deleter 'LDAPMessageDeleter' exists and works in the following.
unique_ptr<LDAPMessage*, LDAPMessageDeleter> msg_ptr(new LDAPMessage*);
c_lib_function(msg_ptr.get());
Though this compiles for me, i'm getting a seg fault. Could this code be at fault here? Is this correct usage of unique_ptr?
It might be easier to do e.g.
LDAPMessage* msg;
c_lib_function(&msg);
// Now we have out pointer (hopefully)
std::unique_ptr<LDAPMessage, LDAPMessageDeleter> msg_ptr(msg);
Of course, the LDAPMessageDeleter have to call the proper function to free the memory (e.g. free is the memory was allocated with malloc).
The problem with the code you show in the question, is that you try to create a pointer to a pointer, but don't make that first-level pointer actually point anywhere.
What you are effectively doing in your code is this:
LDAPMessage** msg;
c_lib_function(msg);
What's happening in the C library, is that the pointer is passed "by reference". Since C doesn't actually have proper references, it's kind of emulated by passing pointers. And passing a "reference" to a pointer is done by using the address-operator to pass the address of the pointer (which then becomes a pointer to the pointer).
Someone in the SO chat developed code valuely like this that I can no longer find:
//ptrptr magic
#include <memory>
template<class T, class deleter>
class ptrptr_type {
public:
ptrptr_type(std::unique_ptr<T, deleter>& ptr)
: uptr(&ptr), tptr(ptr.get()) {}
~ptrptr_type() {if (uptr->get()!=tptr) uptr->reset(tptr);}
operator T**() {return &tptr;}
private:
std::unique_ptr<T, deleter>* uptr;
T* tptr;
};
template<class T, class D>
ptrptr_type<T,D> ptrptr(std::unique_ptr<T, D>& ptr) { return {ptr};}
And the usage of this ptrptr is quite simple:
std::unique_ptr<LDAPMessage, LDAPMessageDeleter> my_ptr; //can be null or initialized, whichever
c_lib_function(ptrptr(my_ptr)); //use ptrptr(my_ptr) whenever you need a T**
That's it. Real simple. http://coliru.stacked-crooked.com/a/644ed001ffd547ae
What happens is ptrptr(my_ptr) creates a temporary ptrptr_type on the stack, which takes the pointer from the unique_ptr. The ptrptr then exposes a pointer to it's internal pointer, which the C function can freely modify. Afterwards, the temporary ptrptr_type is destroyed, and its destructor puts the new value for the pointer back into the original unique_ptr.
This isn't correct usage of the pointer-to-pointer. The function takes a pointer to uninitialized pointer and fills it. In your first example, this is a local variable. If you want it to be managed by unique_ptr, it should still be a local, just contained within the unique_ptr object.
LDAPMessage * msg;
c_lib_function(&msg); // allocates the memory for me
std::unique_ptr< LDAPMessage, LDAPMessageDeleter > // This type contains a ptr
msg_ptr( msg ); // transfer ownership to C++
LDAPMessageDeleter should receive a LDAPMessage *, and pass it to the library to be released if necessary, otherwise pass to free().

C++ class object pointers and accessing member functions

I'm bit new to C++ and try to work things with Qt and came across this confusing thing:
The concepts on various tutorials state something like:
Class *obj;
*obj - will display the value of object stored at the referenced memory
obj - will be address of memory to which it is pointing
so, I would do something like
*obj=new Class();
but if I want to access a function, I have to do obj->function1();
instead of *obj->function1();
-- not sure why, since with normal objects [ normalObj.function1();] would work, since that's the value directly.
So, for pointer objects why do we use memory reference to access the function,
or is it that in case of normal objects also, its always references
P.S: Can someone guide me to a good tutorial of usage of pointers in C++, so that my queries like these can be directly addressed in it.
The * symbol is used to define a pointer and to dereference a pointer. For example, if I wanted to create a pointer to an int, I could do:
int *ptr;
In this example, the * is being used to declare that this is a pointer to an int. Now, when you are not declaring a pointer and you use the * symbol with an already declared pointer, then you are dereferencing it. As you probably know, a pointer is simply an address. When you dereference a pointer, you are obtaining the value that is being pointed to by that address. For example:
int pointToMe = 5;
int *ptr = &pointToMe;
std::cout << *ptr;
This will print out 5. Also, if you are assigning a pointer to a new address and it's not in the declaration, you do not use the * symbol. So:
int pointToMe = 5;
int *ptr;
ptr = &pointToMe;
is how you would do it. You can also deference the pointer to assign a new value to the value being pointed to by the address. Such as:
int pointToMe = 5;
int *ptr = &pointToMe;
std::cout << *ptr; // Prints out 5
*ptr = 27;
std::cout << *ptr; // Prints out 27
Now, -> acts like the deference symbol. It will dereference the pointer and then use the member functions and variables as if you had used . with a non-pointer object. Even with an object that is not a pointer you can use the -> by first getting the address:
CObj object;
(&object)->MemberFunction();
That's just a brief overview of pointers, hope it helps.
You can use the "normal" . to access the objects members, but you have to dereference the pointer first.
Due to operator precedence, this will look like (*obj).member. For those who think this is too much to write, obj->member is a shorter alternative.
If you have an object c of type Class, *c.ptr means dereferencing a pointer ptr that is a member of Class. That is one reason for (*obj).member, which means something else.
Actually, you're wrong. You do:
obj=new Class();
or
Class *obj = new Class;
which are completely different.
Class *obj;
*obj = new Class;
wouldn't compile.
obj is of type Class*, so that's what you can assign to it (and what new Class returns).
More precisely u can do like this
Class obj;
Class* obj_ptr;
obj_ptr = &obj;
// Now onwards you can use the pointer to access data members and function
obj_ptr->a = 10; // Like this

C++: Difference between pointer syntaxes

Alright so I've been getting deeply into C++ as of late and I'm getting everything down. Pointers are finally starting to make sense as far as when I should use them, how to implement them correctly, etc.
However, there was one little question about the fundamental use of pointers that I still had that needed answered. I'll jump right to the code:
With the following class A and function foo(A* bar)...
class A
{}
void foo(A* bar)
{}
... what's the difference between the following calls to foo?
A* a;
A b;
foo(a);
foo(&b);
They both compile fine, and as far as I can remember I haven't had any issues with them.
I think that A b; is instantiated right there, whereas A* a; needs to be created with new (since it hasn't actually created the object, it's just held a 4-byte long reference to a potential A object).
I could, if I am thinking about this correctly, do a = b; (EDIT make that a = &b) and then successfully pass a to foo. But, if I don't do a = &b and foo tries to read the (non-existent) object pointed to by a, it will causes runtime errors.
Also, if the above is correct, then it's assumed I can successfully call foo(&b); just fine.
Am I correct?
Thanks!
Yes, Your understanding is correct.
foo(&b);
passes address of an already existing object of type A as an parameter to function foo().
foo(a);
passes a pointer to the type A as function parameter. To be able to do anything meaningful it must point to a valid A object.It can be done in two ways:
Allocating object on stack:
Create an object of the type A on stack(local storage) & make the pointer a point to this object:
A* a;
A b;
a = &b;
Dynamic Memory allocation:
A *a = new A;
Though, Once you do a dynamic memory allocation you will have to remember to free the alloated memory explicitly after use, or you will have a memory leak:
delete a;
Note that it is always better to avoid dynamic allocations as far as possible, and if you must do so, use Smart pointers instead of raw pointers.
You can't do a = b.
It would have to be a = &b, to set a to the address of b.
You are also correct about the memory management: b is allocated on the stack, while a allocates space only for a pointer and leaves creating the actual object to you.
foo(&b) will work file, where the behavior of foo(a) would be undefined before you initialize *a (such as via a = new A()).
In C++, pointers are first-class objects. A pointer isn't just an invisible reference that needs an associated object to have an identity. That's how Java/C# references work (or most other languages, really), but a pointer is an object in itself.
So A* a declares a pointer. It doesn't point to anything, and it doesn't have to point to anything. And if/when it points to something, it doesn't need to own that something.
So you don't need to do a = new A(). You can do a = &b as well (to have a contain the address of the object b. Or it can point to any other object of type A as well. A pointer is just an object that stores an address. It's key to your understanding that you throw away the notion that it "has an object" which "needs to be created".
It is an object, which contains an address (or it contains the special value null), and if it contains an address, there may or may not be an object of type A at that address.
You are mostly correct. You should not assume that pointers are 4 bytes (for example, it might be 8 on amd64 systems). Also, your assignment should be a = &b; (note the addition of the address operator). Other than that, it sounds pretty reasonable.

basic pointer question in c++ program

I looking for a clarification regarding the pointers. I have compiled the following code in bordland c++ 5.5.1 without any errors. But while i am trying to execute gives a core error.
int main ()
{
int x=10,y=20;
int &a=x;
int &b=y;
int *c;
int *d;
*c=x;
*d=y;
return 0;
}
Basically I am trying to create two reference variable (a,b) and assigned with two variables (x,y). after that I created two pointer variable(c,d) and tried to assign same variables (x,y). This gives me error while exection and not at compilation.
whether I am doing any wrong, this is not a standard assignments of pointer variable. why the pointer assignment is getting failed at this point. Please help me to understand this.
1st Update:
Thanks to all. First, I understood that I am working on a C++ feature (reference variable).
Second, I need to allocate memory for the pointer variables before play with it.
The code you posted is C++, not C. And your problem is that you need to make those pointers actually point at something:
int * c = & x; // make c point at x
* c = 42; // changes x
You have declared c and d as int pointers and you are trying to update their pointed values, they aren't pointing to anywhere valid since you never initialize them with valid memory.
Try c = &x; and then play with c.
You are dereferencing an invalid pointer. 'c' and 'd' were not assigned a memory location and so will be using whatever was previously in memory as their location. You need to do:
int *c = new int;
int *d = new int;
It looks to me like you're not entirely clear on the syntax.
Typing int *c is tricky, because it looks like you're declaring an integer with the name *c. However, this is not the case. This will declare a pointer to an integer, and in C/C++, pointers to a certain type are denoted by appending a * after the type name. Thus, you're declaring a variable of type int* (pointer to an integer), with the name c, even though the spacing makes it look different. For the record, typing int* c yields the same result, and is arguably more readable.
It follows then that typing *c does not reference your variable, as it is actually called c. Instead, what this does is dereference the pointer: it returns whatever object the pointer is pointing to. Or, if the pointer is invalid, cause an error.
If you want to declare a pointer and set it to point to an object at a later point, you need to do this:
int *c;
// stuff goes here
c = &x;
&x will return x's address in memory, which can be assigned to a pointer as a value. Then, you can manipulate the value through the pointer by dereferencing it: e.g. *c = 15.
You have defined two pointer variables c and d but you have not allocated any memory for them. You need to assign some memory to both of them.
Do this:
int *c = &x;
int *d = &y;

Pointer to void in C++?

I'm reading some code in the Ogre3D implementation and I can't understand what a void * type variable means. What does a pointer to void mean in C++?
A pointer to void, void* can point to any object:
int a = 5;
void *p = &a;
double b = 3.14;
p = &b;
You can't dereference, increment or decrement that pointer, because you don't know what type you point to. The idea is that void* can be used for functions like memcpy that just copy memory blocks around, and don't care about the type that they copy.
It's just a generic pointer, used to pass data when you don't know the type. You have to cast it to the correct type in order to use it.
It's a raw pointer to a spot in memory. It doesn't allow any pointer arithmetic like char * or int *.
Here's some examples of usage
http://theory.uwinnipeg.ca/programming/node87.html
It's a pointer to anything -- just a chunk of memory that you can play with -- might be an object, might be a char. You have to cast to do anything useful with it.
Building off my prior posting...
ATTENTION: All memory addresses here are fictional. I'm just making them up to illustrate a point.
Given:
int data[] = {10,11,12};
We now have:
0xffff0000-0xffff0003 with a value of (int)(10)
0xffff0004-0xffff0007 with a value of (int)(11)
0xffff0008-0xffff000b with a value of (int)(12)
(I'm not going to get into big-endian vs little-endian byte ordering here.)
If we have:
int * p = data;
We now have another memory location somewhere else, say:
0xaaaa0000-0xaaaa0003 with a value of (int*)0xffff0000
We can use p[1] [or *(p + 1)] to refer to *(int*)(0xffff0004) [=11] as sizeof(int)=4 and 0xffff0000+sizeof(int) = 0xffff0004.
If we have:
void * v = data;
We now have another memory location somewhere else, say:
0xbbbb0000-0xbbbb0003 with a value of (void*)0xffff0000.
However, void doesn't have any associated sizeof() information. We can't increment or decrement the pointer. We can't dereference to access the data stored in 0xffff0000. We can only utilize the value as a raw memory address.
If we want to use the data stored in (void*)0xffff0000, we first need to cast it to an appropriate type.
That said, (void *) is still quite useful as a means of passing addresses to arbitrary data structures around. For instance, memset(). It doesn't matter whether I'm zero'ing out a struct tm or a struct sockaddr. We just need a pointer to the struct and its size.
(This should go without saying, but... Beware using memset to zero out a class instance and, in doing so, overwriting the virtual pointer table.)
A void pointer cannot point to a class member in C++.