Defining function/method param as pointer and passing without reference - c++

I have a question regarding pointers/references, I couldn't find much information about, so, having this method declaration (C++):
void RequestParser::parseRequest(const char * request)
When I want to use this method, I can call it like this:
requestParser.parseRequest(buffer);
So, going back to the definition the parameter expects a pointer (const char * request), why am I allowed to pass buffer without the reference, this way:
requestParser.parseRequest(&buffer);
This should be the correct way, right? Maybe there is some magic going on behind the scenes, like this:
void RequestParser::parseRequest(const char request[])
I know that you can't pass array as value (at least char arrays), so this is only syntactic sugar for this:
void RequestParser::parseRequest(const char * request)
What am I misunderstanding?

When you pass an array like buffer to parseRequest, array-to-pointer decay occurs,
There is an implicit conversion from lvalues and rvalues of array type to rvalues of pointer type: it constructs a pointer to the first element of an array. This conversion is used whenever arrays appear in context where arrays are not expected, but pointers are:
So you're passing the pointer to the 1st element of the array in fact, it's of type char * (and could convert to const char*).
On the other hand, you can't pass &buffer, which is taking the address of the array and returns the pointer to the array (i.e. char (*)[2048]), it doesn't match the parameter type const char*.

Related

Having trouble with char* arrays

private:
char * args[];
public:
Command(char * a[]){args = a}
When trying to run this code I get
incompatible types in assignment of char** to char* [0]
I am having real trouble understanding what is going on.
First of all, char * args[]; is incorrect. In standard C++ an array has to have a specified size when defined. The (apparent) exception is when you write something like int arr[] = {1,2,3,4,5};, however in this case the compiler automatically sets the size to 5 in this case, as it determines the size at compile time.
Secondly, you cannot copy an array. In your function
Command(char * a[]){args = a}
a decays to a char**. Then you are trying to assign to args, which is an array, a pointer of type char**. This won't work. You cannot assign to an array.
In case you assign/copy arrays, your best bet is to use standard containers such as std::vector.
The declaration char * args[] denotes an array of pointers to non-const char. It's invalid code. Standard C++ does not permit an array of unknown bound as a data member.
Raw arrays are not assignable so also the assignment in the constructor body is invalid code.

How to use strtof endPointer?

Looking at the examples presented by various google results, I don't really understand how the EndPtr works. For an example:
char szOrbits[] = "686.97 365.24";
char* pEnd;
float f1 = strtof (szOrbits, &pEnd);
The function takes the pointer of the pointer that is declared after the char array, does that mean that the actual type and contents of the pointer are irrelevant and the pointer is guaranteed to be allocated right after the array thus making its address the end point?
I tried using it like this:
ret.push_back(EquationPiece(strtof(&Source[mark], (char**)&Source[i])));
where ret is a vector, Source is a char array, mark is where the number begins and i is the next byte after the number but I'm getting some strange results. Is my usage incorrect or should I seek for the bug elsewhere?
Although the reference page describes the parameter pendptr as a reference to a char* object this might be misundestood. In C we have only pointers and the second parameter of strtof is a pointer to a pointer to char.
You can utilize this parameter to get the point in the input char array that could not be used to convert the char array to the output float. If the pointer points to a '\0' than the array has been converted entirely. If it points to something different you can start error handling or further processing of the char array.
You should never cast any pointer when you are not sure what it means. Cast tells the compiler that the programmer knows it better. Depending on the meaning of your EquationPiece it might be useful to pass the endPtr:
ret.push_back(EquationPiece(strtof(&Source[mark], pEnd));

Is C++ Array passed by reference or by pointer?

In school, our lecturer taught us that the entire array was passed by reference when we pass it to a function,.
However, recently I read a book. It says that arrays are passed by pointer by default when passing the entire array to a function. The book further mention that "passing by pointer is very similar to passing by reference", which means that passing by pointer and passing by reference are actually different.
It appears that different source stated differently.
So my question is: In C++, are arrays passed by reference or by pointer when we pass the entire array to a function?
For Example:
void funcA(int []); //Function Declaration
int main()
{
int array[5];
funcA(array); //Is array passed by ref or by pointer here?
}
At worst, your lecturer is wrong. At best, he was simplifying terminology, and confusing you in the process. This is reasonably commonplace in software education, unfortunately. The truth is, many books get this wrong as well; the array is not "passed" at all, either "by pointer" or "by reference".
In fact, because arrays cannot be passed by value due to an old C restriction, there is some special magic that happens with arrays as function arguments.
The function declaration:
void funcA(int[]);
is silently translated into the following:
void funcA(int*);
and when you write this:
funcA(myArray);
it is silently translated into the following:
funcA(&myArray[0]);
The result is that you're not passing the array at all; you pass a pointer to its first element.
Now, at certain levels of abstraction/simplification, you can call this "passing an array by pointer", "passing an array by reference" or even "passing a handle to an array", but if you want to talk in C++ terms, none of those phrases are accurate.
The terminology used by your lecturer is confusing. However, in a function declaration such as
void funcA(int []);
the int[] is just another way of saying int*. So funcA can take any argument that is or can be converted to an int*.
Arrays can decay to pointers to the first element in the right context. This means, for example, that you can assign an array's name to a pointer like this:
int array[42]; // array is of type int[42]
int * arr = array; // array decays to int*
So, when you pass array to funcA,
funcA(array); // array decays to int*
funcA has a pointer to the first element of the array.
But it is also possible to pass arrays by reference. It just requires a different syntax. For example
void funcB(int (&arr)[42]);
So, in your example, you are passing a pointer to the first element of the array, due to the signature of your function funcA. If you called funcB(array), you would be passing a reference.
Pass-by-pointer is a bit of a misnomer. It doesn't happen in C++. There is only pass-by-value and pass-by-reference. Pointers in particular are passed by value.
The answer to your question is: it depends.
Consider the following signatures:
void foo(int *arr);
void bar(int *&arr);
void baz(int * const &arr);
void quux(int (&arr)[42]);
Assuming you are passing an array to each of these functions:
In foo(arr), your array is decayed to a pointer, which is then passed by value.
In bar(arr), this is a compiler error, because your array would decay to a (temporary) pointer, and this would be passed by reference. This is nearly always a bug, since the reason you would want a mutable reference is to change the value of the referent, and that would not be what would happen (you would change the value of the temporary instead). I add this since this actually does work on some compilers (MSVC++) with a particular extension enabled. If you instead decay the pointer manually, then you can pass that instead (e.g. int *p = arr; bar(p);)
In baz(arr), your array decays to a temporary pointer, which is passed by (const) reference.
In quux(arr), your array is passed by reference.
What your book means by them being similar is that passing a pointer by value and passing a reference are usually implemented identically. The difference is purely at the C++ level: with a reference, you do not have the value of the pointer (and hence cannot change it), and it is guaranteed to refer to an actual object (unless you broke your program earlier).

Two pointer related questions

I am looking to understand the following two pieces of code. I am not proficient in C++ and pointers and the operations which can be used with them are still a little unclear to me.
First piece of code
I have trouble understanding what this function actually does. It takes an unsigned char pointer and returns one as well. But the way I currently see it, it just returns a pointer that points to the same place as the original. I might very well be wrong though.
unsigned char* MemoryPool::GetNext(unsigned char* pBlock)
{
unsigned char** ppChunkHeader = (unsigned char**)pBlock;
return ppChunkHeader[0];
}
Edit: I made an attempt at improving the quality of my formatting and clarifying my problems. I appreciate your helpful comments and answers.
Second piece of code
I know that this is a typedef that aliases (would that be a correct term?) a function pointer as under the type name ActorComponent. But what does the function pointer's function type return? If function pointer syntax is:
void (*foo)(int);
Then what is the meaning of the asterisk before the parentheses in the following line of code?
typedef ActorComponent *(*ActorComponentCreator)(void);
It looks to me like the first one doesn't do much. It casts the passed in pointer to unsigned char to be a pointer to pointer to char (a dangerous and old c style cast at that). Then it uses the fact that an array dereference acts like a pointer dereference to return the original pointer to an unsigned char.
typedef ActorComponent *(*ActorComponentCreator)(void);
Creates a function pointer. In this case ActorComponentCreator is the name that refers to a pointer to a function that takes a void and returns a pointer to an ActorComponent.
If we look at this:
typedef ActorComponent *(*ActorComponentCreator)(void);
and change it around a little:
typedef ActorComponent* (*ActorComponentCreator)(void);
it becoems much clearer that it's a function pointer to a function that returns a pointer to an ActorComponent.
Compare with:
typedef int* (*FuncReturningInt)(void);
The first code is given an unsigned char * (treating approximately as if it was a void *; is the code very old, or based on very old software), converts it to a pointer to a pointer to an unsigned char, and then returns the zeroth unsigned char *. So, it treats the location it is passed as if it was the start of an array of unsigned char * values, and returns the zeroth item in that array. In C++, this is not very good code; it would be more respectable as C code.
The second code declares a pointer to function type named ActorComponentCreator. The function returns an ActorComponent *; the function takes no arguments.

memset on static array

I am a little confused about what to pass as the first parameter to memset when you have to set the elements of a static array. I've been searching but I couldn't find the answers to some specific questions I have.
If I have an array declared as:
char arr[10];
I have seen that these two calls are valid and produce the same effect:
memset( arr, 0, 10);
memset( &arr, 0, 10);
My specific questions are:
1- Why do they have the same effect on arr?
2- What is the different between these calls?
3- Which one would be considered the correct one?
Thank you!
Storage duration has nothing to do with it; an array is an array. This expression:
&arr
produces a char (*)[10], i.e., a pointer to an array of char with 10 elements. However, when arr is passed to a function like so:
memset(arr, 0, 10);
it degrades to a pointer to the first element, i.e., a char*. These are not the same thing. The "correct" (idiomatic) call is:
memset(arr, 0, 10);
However, in this case they are both converted to a void* when passed to memset and interpreted in the function as an unsigned char*. Since they both point to the same place it produces the same result.
However, it is important to realize that, when dealing with the true respective types (i.e., not a void*), a pointer to an array is not the same as a pointer to the first element of an array.
For example, incrementing a char (*)[10] will increment the pointer sizeof(char[10]) bytes, while incrementing a char* will increment only one byte.
Why do they have the same effect on arr? What is the different between these calls?
Because the address of an array is the same as the address of its first element (arrays decay into pointers to their first element when passed to a function), it's just that they have a different type. arr has type char[10], that decays into char * when passed to a function. In contrast, &arr has the type char (*)[10] which doesn't change when passed as a function argument.
Which one would be considered the correct one?
As long as the function doesn't expect a specific type, i. e. it accepts void *, either one is good. If the called function, however, expects that either of the types be specified, then the other one should not be used, since then your program would be malformed and invoke undefined behavior.
1- Why do they have the same effect on arr?
They both contain the same value which is the address of the beginning of the array.
2- What is the different between these calls?
arr decays to a pointer to char, i.e. char* (this conversion happens when you pass the name of an array to a function) and &arr is a pointer to an array of char, i.e. char (*)[].
3- Which one would be considered the correct one?
I would use arr. memset accepts a void* which is the reason both work.
Also, note that char arr[10] = {}; can be used to zero initialize the array.