Reputation: 103
How to pass char array[] to function accepting const char* arg
type and what is the most proper way of doing that?
Please ignore the fact that I'm using static 100 buffer in this example:
char buff[100];
sprintf_s(buff, sizeof(buff), "%s", unrelated);
Then I need to pass the buff
to the function accepting const char*
MyFunction(const char* path);
I tried passing it directly: MyFunction(buff)
and it works, but could someone exaplain why? and if there is better way to achieve the same result?
Upvotes: 1
Views: 6428
Reputation: 2278
I tried passing it directly:
MyFunction(buff)
and it works, but could someone exaplain why? and if there is better way to achieve the same result?
A "better way" is open to lots of interpretation. Some here at SO would insist that std::string
is the C++ way and therefore always better than a char[]
but the truth is that it depends on what you're doing. If you are trying to avoid dynamic memory allocations then certainly what you have is acceptable and maybe even the "best way". However, if you are dynamically allocating memory for your buffer array i.e. const char* buff = new char[BUFF_SIZE];
then I would argue that the "better way" is to use std::string
for many reasons not the least of which is that it manages its own memory. In your case you could use it like this.
std::string buff;
MyFunction(buff.c_str());
Why does passing a char[] to a const char* work?
It works because array names decay into pointers to the first element when used in expressions. In your example, char buff[100]
decays to a pointer char*
when it's passed into MyFunction
. You are also allowed to pass non-const arguments as const
because MyFunction
is making the guarantee not to mutate the data. This implicit conversion to const
is fine and allowed.
A properly terminated const char*
is "special" and will have a \0
sentinel value at the end so you do not need to specify the size of the buffer being passed into the function as you would with all other types of arrays. The function being called will check for this null terminator and stop at the appropriate length without going out-of-bounds. I am making an assumption that your MyFunction(const char* path);
checks for a properly null terminated C-string in this way, and if it doesn't then it must be making some potentially dangerous assumptions about path
.
Upvotes: 1
Reputation: 8674
The array "decays" into a pointer to the same memory. So long as the data in the array has a sentinel (NUL-byte) at the end, the callee only needs the pointer and can use the buffer up to the sentinel.
Alternatively, if it's not a C-string (ie. there is no sentinel; the sentinel is the convention that makes an array a C-string), then you'd also need to pass the length of the buffer (generally sizeof(buff)
) so the callee knows how long the buffer is — to avoid overrunning it.
Upvotes: 0
Reputation: 57678
The function signature can be rewriten as:
int MyFunction(char const * buff);
Reading the type, from right to left, the function is requiring a pointer to a constant buffer of char
(read-only). The function is promising it will not change the content of buff
.
You can pass a mutable buffer (non-const) because the function will not modify the buffer. This is allowed.
You cannot pass a pointer to a constant (read only) buffer to a function that will modify the buffer.
int MutateBuffer(char * buffer);
The above is a signature of a function that may write to the buffer. So, passing a read-only buffer to this function is not advised and the compiler will warn about it at least.
Upvotes: 0