I have one function which have argument as char** I need to pass an array value in the same argument how could I pass that?
int fun(char** val)
{
std::cout<<"val:"<<*val<<"\n";
}
int main()
{
char ch[20];
strlcpy(ch, "test", sizeof(ch));
fun(&ch[0]) // here how can I pass the char array getting build issue
}
I think it is best to figure out, what the intent of the function fun is on the basis of the signature, i.e. the type of the parameter:
fun takes a pointer to a pointer to a single character or to the beginning of a bunch of characters. In the first place this means fun wants to have a "reference" to a pointer. This usually means func wants to modify this pointer and pass this modification back to the caller. It seams val is in fact an out parameter containing a pointer. If this is you actual intend, go with this function signature! In this case you would call fun this way:
char *c = NULL;
fun(&c);
// c is set by fun to a certain value
If you simply want to print out the characters it is way easier and much more obvious for a reader of your code to change the signature of fun to
int fun(char *val) { /* ... */ }
This says fun takes a pointer to a single character or a bunch of characters. It will get this pointer by value, any modification to the pointer itself won't be visibly outside of fun. In this case you'll call fun by
char c[] = "Hello World!";
fun(c);
Now, why did you get a build issue: The type of &ch[0] is char *, i.e. a pointer to some characters. But your fun expected char **, i.e. a pointer to a pointer to some characters. That's clearly an issue. And it contradicts the intend expressed by the function signature too: fun wants to have a "reference" to a pointer in order to modify this referenced pointer.
Edit: So, it sounds like you're stuck with a weird API and need to pass an character array into a function expecting a char ** parameter. In this case the other answers provide the correct, albeit still questionable solution:
char c[] = "Hello World";
char *ptr = &c[0];
fun(&ptr);
The ptr points to the first character of c. The variable ptr has itself an address, namely &ptr, which has type char **. So &ptr is the needed "reference" to a pointer to a bunch of characters you can pass to fun.
But be aware of the fact, that fun is free to change the value of ptr, i.e. the address ptr itself points to. It might be possible that, returning from the call to fun, the value of ptr is something completely different, pointing to an address you didn't expect. Heck, it might be even possible that you're expected to call free(ptr) at the end even though you started with an address in ptr to some static memory you shall never call free() to. To know these details you have to read the detailed specifications of the function fun.
ch is a char[] array. &ch[0] is dereferencing the array to access the 1st element, yielding a char, and then is taking the address of that char, yielding a char*. But the function wants a char** instead. So save that char* to a variable and pass the address of that variable to the function, eg:
int main()
{
char ch[20];
strlcpy(ch, "test", sizeof(ch));
char *ptr = ch; // same as: ptr = &ch[0]
fun(&ptr);
}
Related
int main()
{
void fun(char *);
char str[] = "some text";
fun(str);
return 0;
}
void fun(char* ps){
while(*ps){
cout << *ps++;}
cout << endl;
}
So this is one of the examples in a c++ text book by Robert Lafore which illustrates the example of string passed in a function.
While explaining the example it is mentioned that the array address str is passed to the function. This address is constant, but since it is passed by value here. and a copy of it is created in fun().
I am not able to understand this statement as it is c style string which is a constant pointer which behaves similar to the array. The name itself should be the address and and we pass address to the function.
My questions are:
How it is being passed by value if the name itself is address?
Why it is the copy being created when we are passing the pointer argument to the fun()?
I got really confused here.
I might be wrong even in my basics, so an explanation would be great here.
As you probably know, every parameter (variable) of function is stored on the stack (special memory dedicated to local variables) somewhere and acts as new variable.
So your function:
void fun(char* ps)
{
...
}
has variable 'ps' of type 'pointer to char' which exists within the scope of 'fun' function and nowhere else.
So when you use it from other function (such as your main), then you'll have two variables containg pointer to the "some text" string. Namely 'str' inside main and 'ps' inside 'fun' function. The 'ps' is that copy mentioned in the book.
Also you have to distinguish between term 'address' and 'variable'. Address is WHAT is stored and variable is WHERE it is stored.
So for example, this code:
char my_character = 'x';
char *a = &my_character;
char *b = &my_character;
char *c = &my_character;
are three DIFFERENT variables (the one having type char*) but they ALL contain same value - address of my_character variable.
Let us take a look at what is happening in each of the statements in your program.
Statement 1
Here we consider the statement void fun(char *);.
This statement is a declaration for a function named fun that has one parameter of type char* and return type of void. This means that this function takes a pointer to char(char*) as argument by value and returns nothing(void).
Statement 2
Here we consider the statement char str[] = "some text";
This statement defines an array of char named str. That is, the type of str is char [10].
Statement 3
Here we consider the statement fun(str);
This statement calls the function named fun by passing str as an argument. There are 2 important things to note here:
Since the argument is passed by value, str decays to a pointer to char due to type decay. This means, char [10] decays to char *. Remember from statement 1 that the function fun expects a char* as argument and this is exactly what we are supplying/providing it. In particular, we are providing it a pointer to the first character of the array which is nothing but char*.
By value means the argument is copied. But note that in our case the argument is nothing but a char*(from point 1 above due to decay).This is why it is written that:
but since it is passed by value here. and a copy of it is created in fun().
What is the purpose of a function parameter that has two indirection operators?
Since a call by reference is changing the value of the original variable I thought that a function parameter with two indirection operators might change the address of the original value.
But as my attemp below shows, it does not:
void addrchanger(int**);
int main()
{
int value1 = 4;
int* value1ptr = &value1;
std::cout<<&value1<<std::endl;
addrchanger(&value1ptr);
std::cout<<&value1<<std::endl;
//the address of value1 doesn't change.
}
void addrchanger(int** foo)
{
//this is an attempt to change the address of value1 to the next slot
++**foo;
}
The purpose is to pass a pointer to pointer(s) or a pointer to array(s). Such practise is C-like for historical functions like main() char** argv (that is why you also want an argc, because the size cannot be deduced by the pointer). It is also used when you want to be returned a pointer, so you pass a pointer to a pointer, like in many Win32 functions.
For example in StringFromIID
HRESULT StringFromIID(
REFIID rclsid,
LPOLESTR *lplpsz
);
you would pass a double pointer as the 2nd parameter (a wchar_t**) in order to be returned a pointer, which them must be deallocated like the doc says.
Avoid that completely nowadays in C++ and use std::vector in whatever depth is necessary.
The void addrchanger(int** foo) function can change:
the value: (**foo)++ making int value1 to 5
and address: (*foo)++ making value1ptr point to the next space after value1
I believe you expected the ++**foo to move value1 to the next position, which is not the case.
The pointer to pointer is also useful for matrix declarations, but most libraries such as the GNU scientific library, BLAS, OpenGL glLoadMatrixf(), prefer the use of a single pointer.
When p is of type int **,
++**p
increases the value of the int represented by **p.
In order to change the address of the int pointed to, you would use
++*p
With direct access to your variable, you would use one * less for everything:
int *p;
++*p; // increment the int value
++p; // increment the pointer
But inside such a function, every arguments is just a copy, so if you want to change something outside, you need a pointer to it, which means that one more * is used for everything.
function f(int **p) {
++**p; // increment the int value
++*p; // increment the pointer
// you can also increment the argument
// but you can't know whether it will then
// still point to another int pointer:
++p
}
In addition, you can use & instead of * in C++ which is used only for declaring a variable as a reference and then works like a secret, hidden pointer. You use one less * again, like outside the function at the beginning.
function f(int *&p) {
++*p; // increment the int value
++p; // increment the pointer
// you can also not increment the reference itself,
// as it is a hidden pointer.
}
This sounds dangerous because who would want secret pointers? But it is very common in C++ because people like typing less * all over the place.
Assume a function with one parameter of const char* type. When I use a string when calling that function, nothing goes wrong! I would expect that you could only input characters included in the ASCII, for example c or dec 68, but it seem otherwise. Take a look at the code below...
void InitFunction(const char* initString)
{
std::cout << initString;
}
int main()
{
InitFunction("Hello!");
}
When you run the code, no problem, warnings, or errors appear. I did some more testing on this as you can see from the following...
void InitFunction(char initString)
{
std::cout << initString;
}
int main()
{
InitFunction("Hello!"); // compiler error on this line
}
This compiles with an error since Hello! cannot be converted into char. I tried another test, but instead used const char as the function parameter type. The code still compiles with an error. But when I add * to the function parameter type, then everything compiles fine! It appears to me that the const is also necessary.
To my understanding of pointers, the function is asking for a pointer, and the pointer is identified as being a character. But this raises three problems for me.
First, Hello! is not in the form of a pointer. I would expect at least to have to use the reference operator (&).
Second, Hello! is not a char type.
And third, why do we need to include the const?
Am I missing something here? Do pointers and characters work in ways that I don't know?
"Hello!" is a const char array of characters. Arrays are treated like a pointer, they decay to a pointer when used in a function call as an argument. The C++ standard specifies this in order to be compatible with the way that the C language standard specifies arrays are to be treated.
By the way this array decay to a pointer happens with other cases where an array is being used where a pointer or the address operator could be used such as an assignment statement. See also Arrays are Pointers?
So "Hello!" will be put into the argument list of InitFunction() as a pointer which points to where the compiler has stored the array of characters with the terminating zero character added. When the compiler generates the code for the function call, the pointer to the array of characters used as an argument to the function is const char *, a pointer to a char which is const and should not be changed.
When you have the function prototype as InitFunction(const char *), the compiler is fine with a function call such as InitFunction("Hello!");. What you are doing is providing a const char * that points to "Hello!".
However if you remove the const then since "Hello!" is a const the compiler complains. The compiler complains because a const variable is being used in a function call whose argument list is non-const indicating that the function may change what the pointer is pointing to. Since "Hello!" is not supposed to be changed, since it is const, the compiler issues an error.
If you remove the asterisk, change const char * to const char, then since "Hello!" is a char array which the compiler then decays into a pointer to the first element of the array, the compiler complains as you are trying to use a pointer for an argument that is not a pointer. In this alternative the problem is the actual data type, char versus char * is the problem.
The following lines of code would also be acceptable:
const char *p = "Hello!"; // create a pointer to an series of characters
char x1[] = "Hello!"; // create an array of char and initialize it.
char *p2 = x1; // create a pointer to char array and initialize it.
char *p3 = x1 + 2; // create a pointer to char array and initialize it with address of x1[2].
InitFunction (p); // p is a const char *
InitFunction (x1); // x1 decays to a char *
InitFunction (p2); // p2 is a char *
InitFunction (p3); // p3 is a char *
InitFunction (x1 + 3); // called with address of x1[3].
Note also C++ has an actual character string type, string, that results in a dynamic character text string whose underlying physical memory layout normally includes a pointer to an array of characters. The C style array of characters that is labeled a string is not the same thing as the C++ string type.
the function is asking for a pointer
Correct.
and the pointer is identified as being a character
No, a pointer is a not a character. A pointer is a pointer. This pointer points to one or more characters, i.e. an array of characters. And that's exactly what your string literal is.
First, Hello! is not in the form of a pointer.
Yes, it is. The string literal "Hello!" has type const char[7] and this decays to a pointer.
I would expect at lest to have to use the reference operator (&).
That's the address-of operator. You don't always need it to get a pointer. Example: this.
Second, Hello! is not a char type.
No, but each constituent character is.
And third, why do we need to include the const?
Because the string literal "Hello!" has type const char[7]. Dropping the const would violate const-correctness and is therefore not permitted.
This throws an error since Hello! cannot be converted into char.
That's right. A char is one byte. The string "Hello!" is not one byte. It is a string.
A C-string is typically/conventionally/usually provided in const char* form.
You should read the chapter in your book about this subject as it's a fundamental of the language. It has nothing to do with ASCII (text encodings are irrelevant to storing a sequence of bytes).
I have a function
ValArgument(char* ptr){
char str[] = "hello world";
ptr = &str[0];
}
In this function, I want to init a char array and add it to the char pointer ptr. I call the function like that:
char* ptr= NULL;
ValArgument(ptr);
The pointer returned still has the value NULL. Why? I expected that the pointer will point onto the char array str[].
The pointer returned still has the value NULL. Why?
Because you passed the pointer by value. That means that the function is given a separate copy of the pointer, and any changes it makes to the pointer will not affect the caller's copy.
You can either pass by reference:
void ValArgument(char *& ptr)
// ^
or return a value:
char * ValArgument();
I expected that the pointer will point onto the char array str[].
No; once you've fixed that problem, it will point to the undead husk of the local variable that was destroyed when the function returned. Any attempt to use the pointer will cause undefined behaviour.
Depending on what you need to do with the string, you might want:
a pointer to a string literal, char const * str = "hello world";. Note that this should be const, since string literals can't be modified.
a pointer to a static array, static char str[] = "hello world";. This means that there is only one string shared by everyone, so any modification will affect everyone.
a pointer to a dynamically allocated array. Don't go there.
a string object, std::string str = "hello world";. This is the least error-prone, since it can be passed around like a simple value.
Can I pass an array to printf directly:
char text[1024] = "text";
printf("%s", text);
Or should I explicitly cast it to a char pointer:
char text[1024] = "text";
printf("%s", (char*) text);
I'm asking because I thought maybe it copies the array elements directly into the va_list instead of putting just a pointer to the first element.
Yes, you can pass an array directly. Exactly, name of array represents address of the array which makes no difference with char *.
(char*)text and text hardly make any difference in this example! Base address of an array decays into a pointer when passed as a function argument.
In fact, even if text was not a char array, still it would hardly make any difference to printf because it is a variable argument function
int printf(const char *format, ...);
and all it cares is about the first argument. Logic might go wrong but printf doesn't care!
Short answer, yes, arrays in C _are_a pointer to their first element. (Edit: Longer answer, well, actually, arrays in C are identifiers or labels which are just names, but when used as part of an expression that doesn't preface them with & or sizeof they get converted into or otherwise evaluated as pointers).
Even longer answer: You see, functions can't really receive an array as an argument, but the compiler has to send them something, so it sends them a pointer. Thus the first sentence should probably start with "As far as functions like printf() are concerned..."
Some functions purport to take an array, but that's just an illusion. These two functions are the same.
func(char *a);
func(char a[]);
The C FAQ entry below goes into more detail about the subtle differences between arrays and pointers:
char a[] = "this";
char *b = "that";
a[0] generates completely different code than b[0] yet they are roughly equivalent in that the subscripting operator [] gives us the expected result.
Interestingly, the format specifier "%s\n" is also passed to printf() as a pointer.
http://www.lysator.liu.se/c/c-faq/c-2.html
Isn't an array/arrayname always a pointer to the first element in C?
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be replaced by an expression of type "pointer to T" whose value is the address of the first element of the array.
When you write
printf("%s", text);
the expression text is replaced by a new expression of type char * whose value is &text[0], and this pointer value is what gets passed to printf. This means you don't have to cast the argument. It also means that you cannot pass an array expression as a function parameter and have the called function receive it as an array type. The conversion happens before the function is called.
names of pointers and arrays are exchangeable. (Besides the memory allocation)
When you have
char *a = "abcdef";
char b[5];
You could write
char z = a[2]; // 'c'
char x = *b;
char y = *(b+2);
But you can't do
b ++;
You may consider array b as char * const b as a unmodifyable pointer