Passing in and modifying an array in a function - c++

I have been looking at other posts and trying to get this working for a bit, but can't seem to manage it.
Basically I want to pass a "char myArray[10]" though into a function, have the function assign the values and then hand it back. It generally looks like this at the moment:
int MyClass::GetArray(char array[10])
{
char p[10];
... // a value is assigned to p
memcpy(&array, &p, sizeof(p)); // Here array ends up being 0x3232323232323232 <Error reading characters of string.>
return 0;
}
Called with:
char array[10];
myclass.GetArray(array);
So, I assume I need to pass the array through as a reference to the array[10] created before calling the function. But for that I am unsure how to create a pointer to a fixed array without making it either a general char* pointer or a pointer to an array of chars.
Secondly is the memcpy error (in the code comments above). I'm not sure if that is related or not though.

Then thing is that when you pass an array to a function, it decays to a pointer. So when you use the address-of operator & on array in the function, you're taking the address of the pointer, meaning you get a pointer to a pointer.
That, by the way, leads to undefined behavior.
Other than that it's all okay, you don't have to pass the array (or rather, pointer) by reference. It's just not very... C++-ish. :)

Related

C++ char pointer to char variable

I'm given a method header as so:
char* thisMethod(char* input){}
is it possible to say,
char var = input[0];
? I know that "input" will be in the form of a char array.
I'm obviously new to C++ pointers are throwing me off. I tried researching how to work with char pointer function arguments but couldn't find anything specific enough to help. Thanks for the help.
There is a misconception that may lead you into further troubles:
I know that "input" will be in the form of a char array.
NOPE: By the scope of that function, input is a pointer to a character. The function has no way to know where such a pointer comes from.
If it has been taken from an array upon calling the function than it will be a pointer to the first element of that array.
Because pointer have an arithmetic that allows to add offsets and because the [] operator applied to pointers translates as a[b] = *(a+b) by definition, in whatever code, if a is a pointer, *a and a[0] are perfect synonymous.
Think to an array as a sequence of boxes and a pointer as your hand's index finger
adding an offset to a finger (like finger+2) means "re-point it aside" and de-referencing it (like *finger) means "look inside what it points to".
The [] operator on pointers is just a shortcut to do both operations at once.
Arrays are another distinct thing. Don't think to them when dealing with pointers, since -in more complex situations, like multidimensional array or multi-indirection pointers - the expression a[b][c] won't work anymore the same way.
There are two ways to get a value from a pointer, * and []. The following are equivalent:
char var1 = *input;
char var2 = input[0];
Using the brackets is more common when you know you were passed an array, since it allows you to supply an index. You need some way of knowing where the end of the array is so that you don't attempt any access past it, your function is missing that important detail.
As long as it's inside the function and input points to something valid ( not NULL/nullptr and not a garbage location ) then doing char var = input[0]; is just fine. It's the same as char var = *input.
P.S If it's supposed to be a string I recommend using std::string.

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).

a couple of simple questions about basic pointer use in c++ and the c++ memory model

I've been studying along with the Stanford courses on iTunes U and have hit pointers in C++. I think I understand how pointers work, but I just want to check how to do some simple stuff. Let's say I want to create a dynamic array:
double *array;
At this point there's a variable called "array" in the stack and nothing in the heap. First question - what's stored in "array" at this point? A pointer to some nonsense piece of memory?
I then allocate memory using "new":
array = new double[10];
Second question - at this point, what's stored in "array"? A pointer to some contiguous piece of memory big enough to hold ten doubles? (Sorry for the simple questions, but I really want to make sure I understand)
I assign the double 2.0 to each element in the array:
for(int i=0; i<array.length(); i++) array[i]=2.0;
Third question - is this different from using the dereference operator to assign? (i.e., *array[i]=2.0). I then pass the array to some other function:
myFunc(double array[]){
for(int i=1; i<array.length(); i++){
array[i]=array[i]*array[i-1];
}
}
Fourth question - on the pass to myFunc, since array is an array of pointers to doubles, and not an array of doubles, it passes by reference without "&", right? That means the operations in my loop are affecting the actual data stored in "array". What if I wanted to pass by value, so that I wouldn't be touching the data in "array"? Would I use
myFunc(double *array[]){...}?
Last question - what if I wanted to manipulate the memory addresses for the contents of "array" for some reason? Could i use
someVar = &array[5];
to assign the the hex address of array[5] to someVar?
I've read the section on pointers in the reader and watched the Binky video a dozen times and it still doesn't make sense. Any help would be greatly appreciated.
EDIT: Thanks a lot to everyone who answered so far. If you wouldn't mind I just have one more question. In the declaration double *array;, "array" is declared as a pointer to a double, but once I use "new" to assign it, "array" ceases being a pointer to a double, and becomes an array of doubles, right?
array contains junk data - whatever was in that memory location before array existed is still there. If you try to play with it you're going to shoot yourself in the foot, which is why you need to assign it to a valid memory location, (hence the ensuing call to new[]).
Yes, array now contains a pointer (memory address) to some contiguous piece of memory big enough to hold ten doubles.
*array[i]=2.0 won't actually compile. array[i] results in a double, and you can't use the dereference operator on a double.
What you're passing is that address to the first element in the array. So you are passing the pointer by value, and the array by reference (as the pointer is a reference to the array.) To pass the array itself by value you'd have to have one parameter for each entry. You could also copy the array and send in the copy, but the copy itself would be passed by reference, too.
double* someVar = &array[5]; will return to you a pointer to the 6th element of the array. array[5] gives you the double, and taking the address of it (with &) will give you the memory address (pointer) of that double.
Yep, that's what's happening
Most definitely. More specifically, a pointer to the beginning of a contiguous piece of memory.
Not in this case; * (for dereference) is a unary operator, and yet you have passed it two arguments. You can be sure it is multiplication that is performed (or an overloaded version of it) - also, what could array[i](*array[i-1]) mean? you can't dereference something that isn't a pointer (or doesn't have the unary * operator overloaded)
You're only passing the pointer by value and not the data. If you want to pass the data by value (make it unchanged outside the function), you'd have to copy it first, and pass that (or just use a vector)
Yes, you're just getting the address of a part of contiguous memory, and you can store the address and modify the dereferenced value elsewhere, the array will be modified also.
Also, be weary that when you allocate on the heap, you have to delete the memory afterwards. In this case, you would use delete[] array;
After declaration, the array variable contains an arbitary value. You're not allowed to do anything with that value. After new, it contains a pointer to a contiguous range of memory large enough to hold 10 doubles. *array[i]=2.0 is an error (that would imply that array is an array of pointers to double). Indexing operator [] is just a syntactic sugar for *(array+i)=2.0.
Forth question: SAY WHAT?? You don't have an array of pointers to doubles anywhere in that code. In functions, void f(double *x) and void f(double x[]) are THE SAME THING: a pointer to double. If you pass to f an array, x will receive the address of the first element (which is the VALUE of an array).
You can't pass arrays by value. Alternatively, they are always passed by value (as everything else in C), but note that the VALUE of an array is the address of its first element.
Your last question: I have no idea what you're trying to achieve, but the question clearly shows that you're confused. An address is an address, there's no such thing as "hex address".

Cannot convert from 'int *' to 'int []'?

I know this might be a common question but I have tried to search but still cannot find a clear answer.
I have the following code:
int* f() {
int a[] = {1,2,3};
return a;
}
int main() {
int a[] = f(); // Error here
getch();
return 0;
}
This code produces the error message: "Cannot convert from 'int *' to 'int []'"
I found this quite strange because I have read that pointer and array are similar. For example, we can use a[i] instead of *(a + i).
Can anyone give me a clear explanation, please?
There are actually two errors in this code.
Firstly, you are returning the address of a temporary (the int array within f), so its contents are undefined after the function returns. Any attempt to access the memory pointed to by the returned pointer will cause undefined behaviour.
Secondly, there is no implicit conversion from pointers to array types in C++. They are similar, but not identical. Arrays can decay to pointers, but it doesn't work the other way round as information is lost on the way - a pointer just represents a memory address, while an array represents the address of a continuous region, typically with a particular size. Also you can't assign to arrays.
For example, we can use a[i] instead of *(a + i)
This, however, has little to do with the differences between arrays and pointers, it's just a syntactic rule for pointer types. As arrays decay to pointers, it works for arrays as well.
The type int[] doesn't actually exist.
When you define and initialize an array like
int a[] = {1,2,3};
the compiler counts the elements in the initializer and creates an array of the right size; in that case, it magically becomes:
int a[3] = {1,2,3};
int[] used as a parameter to a function, instead, it's just plain int *, i.e. a pointer to the first element of the array. No other information is carried with it, in particular nothing about the size is preserved. The same holds when you return a pointer
Notice that an array is not a pointer: a pointer can be changed to point to other stuff, while an array refers always to the same memory; a pointer does not know anything about how big is the space of memory it points to, while the size of an array is always known at compile time. The confusion arises from the fact that an array decays to a pointer to its first element in many circumstances, and passing it to a function/returning it from a function are some of these circumstances.
So, why doesn't your code work? There are two big errors:
You are trying to initialize an array with a pointer. We said that an int * doesn't carry any information about the size of the array. It's just a pointer to the first element. So the compiler cannot know how big a should be made to accomodate the stuff returned by f().
In f you are returning a pointer to a variable that is local to that function. This is wrong, because a pointer does not actually store the data, it only points to where the data is stored, i.e. in your case to the a local to f. Because that array is local to the function, it ceases to exist when the function exits (i.e. at the return).
This means that the pointer you are returning points to stuff that does not exist anymore; consider the code:
int * a = f();
This initialization works, and you can try to use a later in the function, but a will be pointing to the no-longer existent array of f; in the best case your program will crash (and you'll notice immediately that you've done something wrong), in the worst it will seem to work for some time, and then start giving strange results.
int * and int [] are similar but different.
int * is a real pointer, meanwhile int[] is an array reference ( a sort of "constant pointer" to the begin of the data) wich cannot be modified. So, a int * can be threated like a int [] but not viceversa.
You can use a[b] and*(a+b) interchangeably because that is exactly how a[b] is defined when one of a or b is a pointer and the other is of integer or enumeration type.
Note: This also means that expressions like 42[a] are perfectly legal. Human readers might object strongly, but the compiler won't bat an eye at this.