I am trying to understand char pointer in C more but one thing gets me.
Supposed I would like to pass a char pointer into a function and change the value that pointer represents. A example as followed:
int Foo (char *(&Msg1), char* Msg2, char* Msg3){
char *MsgT = (char*)malloc(sizeof(char)*60);
strcpy(MsgT,"Foo - TEST");
Msg1 = MsgT; // Copy address to pointer
strcpy(Msg2,MsgT); // Copy string to char array
strcpy(Msg3,MsgT); // Copy string to char pointer
return 0;
}
int main() {
char* Msg1; // Initial char pointer
char Msg2[10]; // Initial char array
char* Msg3 = (char*)malloc(sizeof(char) * 10); // Preallocate pointer memory
Foo(Msg1, Msg2, Msg3);
printf("Msg1: %s\n",Msg1); // Method 1
printf("Msg2: %s\n",Msg2); // Method 2
printf("Msg3: %s\n",Msg3); // Method 3
free(Msg1);
free(Msg3);
return 0;
}
In the above example, I listed all working methods I know for passing char pointer to function. The one I don't understand is Method 1.
What is the meaning of char *(&Msg1) for the first argument that is passed to the function Foo?
Also, it seems like method 2 and method3 are widely introduced by books and tutorials, and some of them even referring those methods as the most correct ways to pass arrays/pointers. I wonder that Method 1 looks very nice to me, especially when I write my API, users can easily pass a null pointer into function without preallocate memory. The only downside may be potential memory leak if users forget to free the memory block (same as method 3). Is there any reason we should prefer using Method 2 or 3 instead Method 3?
int f(char* p) is the usual way in C to pass the pointer p to the function f when p already points to the memory location that you need (usually because there is a character array already allocated there as in your Method 2 or Method 3).
int f(char** p) is the usual way in C to pass the pointer p to the function f when you want f to be able to modify the pointer p for the caller of this function. Your Method 1 is an example of this; you want f to allocate new memory and use p to tell the caller where that memory is.
int f(char*& p) is C++, not C. Since this compiles for you, we know you are using a C++ compiler.
Consider what happens when you take an argument of type int& (reference to int) :
void f(int &x) {
x++;
}
void g(int x) {
x++;
}
int main() {
int i = 5;
f(i);
assert(i == 6);
g(i);
assert(i == 6);
}
The same behaviour can be achieved by taking a pointer-to-int (int *x), and modifying it through (*x)++. The only difference in doing this is that the caller has to call f(&i), and that the caller can pass an invalid pointer to f. Thus, references are generally safer and should be preferred whenever possible.
Taking an argument of type char* (pointer-to-char) means that both the caller and the function see the same block of memory "through" that pointer. If the function modifies the memory pointed to by the char*, it will persist to the caller:
void f(char* p) {
(*p) = 'p';
p = NULL; //no efect outside the function
}
int main() {
char *s = new char[4];
strcpy(s, "die");
char *address = s; //the address which s points to
f(s);
assert(strcmp(s, "pie") == 0);
assert(s == address); //the 'value' of the variable s, meaning the actual addres that is pointed to by it, has not changed
}
Taking an argument of type char*& ( reference-to-(pointer-to-char) ) is much the same as taking int&:
If the function modifies the memory pointed to by the pointer, the caller will see it as usual. However, if the function modifies the value of the pointer (its address), the caller will also see it.
void f(char* &p) {
(*p) = 'p';
p = NULL;
}
int main() {
char *s = new char[4];
strcpy(s, "die");
char *address = s; //the address which s points to
f(s);
assert(strcmp(address, "pie") == 0); //the block that s initially pointed to was modified
assert(s == NULL); //the 'value' of the variable s, meaning the actual addres that is pointed to by it, was changed to NULL by the function
}
Again, you could take a char** (pointer-to-pointer-to-char), and modify f to use **p = 'p'; *p = NULL, and the caller would have to call f(&s), with the same implications.
Note that you cannot pass arrays by reference, i.e. if s was defined as char s[4], the call f(s) in the second example would generate a compiler error.
Also note that this only works in C++, because C has no references, only pointers.
You would usually take char** or char*& when your function needs to return a pointer to a memory block it allocated. You see char** more often, because this practice is less common in C++ than in C, where references do not exist.
As for whether to use references or pointers, it is a highly-debated topic, as you will notice if you search google for "c++ pointer vs reference arguments".
Related
This question already has answers here:
Need of Pointer to pointer
(5 answers)
Closed 9 years ago.
I am new to C/ C++.
I was going through some of the coding questions related to trees and came across this double pointer notation. Can we do the same things using single pointer as first argument in the below function as we can do with double pointers.
void operate(struct Node *root, struct Node **head_ref){ //do something}
There are two ways of interpreting a pointer; a reference to something, or an array. Considering this is a tree, this is probably the first: a reference to another pointer.
Every argument to a function in C is passed by value, which means that if you change the pointer inside the function, it won't be changed outside. To guarantee it is also changed outside, you can use a reference to the pointer: double pointers. You can consider the following example.
void function(int a) {
a = 5;
}
Even if a is changed above, it is not changed outside of the function. But in this other case,
void function(int * a) {
*a = 5;
}
the value a is changed outside the function as well. The same thought process can be applied to a pointer(which is also a value).
When you want a function to take care of malloc, free is the main reason.
This is useful if you want to encapsulate memory allocation.
For example some init(struct some_struct **), free(struct some_struct **).
And let functions take care of malloc, free. Instead of allocating on stack.
For example a function that packs a string of unknown length.
size_t pack_struct(char** data, const struct some_struct * some_struct)
{
/**
* #brief buffer
* #note verify the needed buffer length
*/
char buffer [256]; // temporary buffer
*data = 0;
//const char* package_pattern = "%cW ;%u.%u;%s%c";
size_t len = sprintf(buffer, weight_package_pattern,
START_CHARACTER,
some_struct->ts.tv_sec,
some_struct->ts.tv_usec,
some_struct->string_of_unknown_length, // but no more then buffer
STOP_CHARACTER);
if(len == 0) {
perror("sprintf failed!\n");
return len;
}
// len++; // for end character if wanna some, see sprintf description
*data = (char*)malloc(len*sizeof(char)); // memory allocation !
strncpy(*data, buffer, len);
return len;
}
However such technic should be avoided when programming in C++.
Double pointer is normally used when allocating memory.
#include <stdlib.h>
void new_malloc(void **p, size_t s) {
*p = malloc(s);
/* do something */
}
int main() {
int *p;
new_malloc((void **)&p, sizeof(int) * 10);
}
I have a problem. I have a function in my dll which is defined as below:
int function(char *inVal, char *outVal, int *retVal)
I successfully load my dll in a console application using LoadLibrary, and I call my function with function pointer:
typedef int (__cdecl *functionPtr)(char *, char *,int *);
then I pass my inVal to my function:
char * inVal = "input";
Now I want to get my outVal and retVal, I have got the retVal successfully but my outVal is NULL:
int retVal = 0;
char outVal[200] = {0};
then I call my function:
int return = functionLNK(inVal , outVal, &retVal)
any clue?!!
EDIT 1:
The code is as below:
int function(char *inVal, char *outVal, int *retVal)
{
PKI_Buf inBuf, signBuf, pemBuf;
......
outVal = (char*)pemBuf.data;
//I check outVal in this point and it is not NULL
}
The problem is with function. You pass outVal by value which means that the pointer you have inside the function is a copy of the one you passed in. Then you assign to that pointer with outVal = (char*)pemBuf.data;. All you've done is modified the copy. No change occurs on the outside.
This isn't the only problem with your approach though. You're also trying to pass a pointer to a member of an object that is about to go out of scope. pemBuf has automatic storage duration (because it is local to function) which means it will be destroyed when it returns. Then your pointer will be pointing at an invalid object.
Instead, what you want to do is copy the contents of pemBuf.data over to the array elements pointed at by outVal. You can do this with std::copy or strcpy. However, you have another issue which is you don't pass in the size of your buffer (and I don't know the size of the pemBuf.data array). Assuming you know how much to copy as N, however, you could do:
std::copy(pemBuf.data, pemBuf.data + N, outVal);
However, your code is very C-like - using C-style strings, output parameters, and so on. I recommend that you start using std::string.
If I have a function that takes int *&, what does it means? How can I pass just an int or a pointer int to that function?
function(int *& mynumber);
Whenever I try to pass a pointer to that function it says:
error: no matching function for call to 'function(int *)'
note: candidate is 'function(int *&)'
It's a reference to a pointer to an int. This means the function in question can modify the pointer as well as the int itself.
You can just pass a pointer in, the one complication being that the pointer needs to be an l-value, not just an r-value, so for example
int myint;
function(&myint);
alone isn't sufficient and neither would 0/NULL be allowable, Where as:
int myint;
int *myintptr = &myint;
function(myintptr);
would be acceptable. When the function returns it's quite possible that myintptr would no longer point to what it was initially pointing to.
int *myintptr = NULL;
function(myintptr);
might also make sense if the function was expecting to allocate the memory when given a NULL pointer. Check the documentation provided with the function (or read the source!) to see how the pointer is expected to be used.
Simply: a reference to a pointer.
In C, without references, the traditional way to "relocate" a pointer, is to pass a pointer to a pointer:
void c_find(int** p, int val); /* *p will point to the node with value 'val' */
In C++, this can be expressed by the reference syntax, to avoid the awkward double dereference.
void cpp_find(int*& p, int val); // p will point to the node with value 'val'
It means a reference to a pointer to an int. In other words, the function can change the parameter to point to something else.
To pass a variable in, just pass an int*. As awoodland points out, what's passed in must be an l-value.
Edit:
To build on awoodland's example:
#include <iostream>
void foo(int*& var)
{
delete var;
var = new int;
}
int main(int argc, char* argv[])
{
int* var = NULL;
std::cout << var << std::endl;
foo(var); // this function can/will change the value of the pointer
std::cout << var << std::endl;
delete var;
return 0;
}
function takes a single parameter, mynumber which is a reference to a pointer to an int.
This is useful when you need to pass a pointer to a function, and that function might change the pointer. For example, if you function is implemented like this:
function(int*& mynumber)
{
if( !mynumber )
mynumber = new int;
*mynumber = 42;
}
...Then something like this might happen in the calling code:
int main()
{
int* mynumber = 0;
function(mynumber); // function will change what "mynumber" points to
cout << *mynumber;
return 0;
}
This is a reference to a pointer to int - you would have to pass in the address of an int to this function, and be aware that the function could change the pointer through the reference.
Dumb example:
void func(int*& iref)
{
iref = new int;
}
int main()
{
int i(0);
int* pi(&i);
func(pi);
// pi no longer equal to &i
return 0;
}
I am reading a post on Stack Overflow and I saw this function:
advance_buf( const char*& buf, const char* removed_chars, int size );
What does char*& buf mean here and why do people use it?
It means buf is a reference to a pointer, so its value can be changed (as well as the value of the area it's pointing to).
I'm rather stale in C, but AFAIK there are no references in C and this code is C++ (note the question was originally tagged c).
For example:
void advance(char*& p, int i)
{
p += i; // change p
*p = toupper(*p); // change *p
}
int main() {
char arr[] = "hello world";
char* p = arr; // p -> "hello world";
advance(p, 6);
// p is now "World"
}
Edit: In the comments #brett asked if you can assign NULL to buff and if so where is the advantage of using a reference over a pointer. I'm putting the answer here for better visibility
You can assign NULL to buff. It isn't an error. What everyone is saying is that if you used char **pBuff then pBuff could be NULL (of type char**) or *pBuff could be NULL (of type char*). When using char*& rBuff then rBuff can still be NULL (of type char*), but there is no entity with type char** which can be NULL.
buf's a (C++) reference to a pointer. You could have a const char *foo in the function calling advance_buf and now advance_buf can change the foo pointer, changes which will also be seen in the calling function.
How can we access variables of a structure? I have a struct:
typedef struct {
unsigned short a;
unsigned shout b;
} Display;
and in my other class I have a method:
int NewMethod(Display **display)
{
Display *disp=new Display();
*display = disp;
disp->a=11;
}
What does **display mean? To access variables of struct I have used ->, are there other methods too?
As Taylor said, the double asterisk is "pointer to pointer", you can have as many levels of pointers as you need.
As I'm sure you know, the arrow operator (a->b) is a shortcut for the asterisk that dereferences a pointer, and the dot that accesses a field, i.e.
a->b = (*a).b;
The parentheses are necessary since the dot binds tighter. There is no such operator for double asterisks, you have to first de-reference to get to the required level, before accessing the fields:
Display **dpl = ...;
(*dpl)->a = 42;
or
(**dpl).a = 42;
Think of it as *(*display). When you want to pass the address of an integer to a function so that you can set the integer, you use:
void setTo7 (int *x) {
*x = 7;
}
: : :
int a = 4;
setTo7 (&a);
// a is now 7.
It's no different from what you have except that you want to set the value of a pointer so you need to pass the pointer to that pointer. Simple, no?
Try this out:
#include <stdio.h>
#include <string.h>
static void setTo7 (int *x) { *x = 7; }
void appendToStr (char **str, char *app) {
// Allocate enough space for bigger string and NUL.
char *newstr = malloc (strlen(*str) + strlen (app) + 1);
// Only copy/append if malloc worked.
if (newstr != 0) {
strcpy (newstr, *str);
strcat (newstr, app);
}
// Free old string.
free (*str);
// Set string to new string with the magic of double pointers.
*str = newstr;
}
int main (void) {
int i = 2;
char *s = malloc(6); strcpy (s, "Hello");
setTo7 (&i); appendToStr (&s, ", world");
printf ("%d [%s]\n",i,s);
return 0;
}
The output is:
7 [Hello, world]
This will safely append one string value to another, allocating enough space. Double pointers are often used in intelligent memory allocation functions, less so in C++ since you have a native string type, but it's still useful for other pointers.
**display is just a double pointer (a pointer to a pointer of type Display).
The ** means that its a pointer-to-a-pointer. Basically it points to another pointer that then points to something else, in your case a Display structure.
If you called the function with only the object you can access the members with the . operator.
int NewMethod(Display display)
{
Display disp = display;
disp.a=11;
}
But this way you are not modifying directly the Display display object but a local copy. Your code suggests that the changes to the object are needed outside of the function so your only option is the one you described (well, maybe passing the argument by refference but the syntax then would more or less the same (->)).
Since disp is a Pointer you have to use ->
If you just have a "normal" variable (i.e. on the stack)
Display d;
you can write d.a
A struct is the same as a class. The only difference (I am aware of) is that all members are public by default.
You can do (*disp).a=11;
it is called dereferencing