Pointer Pointer Methods C++ - c++

I have two questions:
1) How can I make an array which points to objects of integers?
int* myName[5]; // is this correct?
2) If I want to return a pointer to an array, which points to objects (like (1)) how can I do this in a method? ie) I want to impliment the method:
int **getStuff() {
// what goes here?
return *(myName); // im pretty sure this is not correct
}
Thanks for the help!

How can I make an array which points
to objects?
int * myName[5]; /* correct */
If I want to return a pointer to an
array, which points to objects (like
(1)) how can I do this in a method?
Technically, you write this function:
int * (* getStuff() )[5] {
return &myName;
}
That returns a pointer to that array. However, you don't want to do that. You wanted to return a pointer to the first element of the array:
int ** getStuff() {
return myName; /* or return &myName[0]; */
}
That way, you can now access items as you want like getStuff()[0] = &someInteger;

Note that your code,
int* myName[5];
declares an array containing 5 values, each of which is a "pointer to int", which is what you asked.
However this being C++, that's all it does. As a Python scripter, that might cause you some surprises.
It does not give any of those 5 pointers sensible values, and it does not create any integers for them to point to.
If you put it in a function body, then it creates the array on the stack. This means that the array will cease to exist when the current scope ends (which, to put it simply, means when you get to the enclosing close-curly, so for example return does it). So in particular, the following code is bad:
int **myFunction() {
int *myArray[5];
return myArray;
} // <-- end of scope, and return takes us out of it
It might compile, but the function returns a pointer to something that no longer exists by the time the caller sees it. This leads to what we call "undefined behaviour".
If you want the array to exist outside the function it's created in, you could create one on the heap each time your function is called, and return a pointer, like this:
int **myFunction() {
int **myArray = new int[5];
return myArray;
}
The function returns a different array each time it's called. When the caller has finished with it, it should destroy the array, like this:
delete[] myArray;
otherwise it will never be freed, and will sit around using up memory forever (or when your program exits on most OSes).
Alternatively, you can use the keyword "static" to create an array with "global storage duration" (meaning that it exists as long as the program is running, but there's only one of it rather than a new one each time). That means the function returns the same array each time it's called. The caller could store some pointers in it, forget about it, call the function again, and see the same pointers still there:
int **myFunction() {
static int *myArray[5];
return myArray;
}
Note how similar this code is to the very bad code from earlier.
Finally, if you just want to create an array of integers, not an array of pointers to integers, you can do this:
int myArray[5] = { 1, 2, 3, 4, 5};
That actually creates 5 integers (meaning, it assigns space which can store the integer values themselves. That's different from the array of pointers, which stores the addresses of space used to store integer values).
It also stores the specified values in that space: myArray[0] is now 1, myArray[1] is 2, etc.

1) Correct - this is an array of 5 pointers to ints
2) You can return a pointer to an array of pointers to ints by returning a pointer to the first element of that array. This has two levels of indirection, so you need two asterisks. You can also return the array normally, since arrays automatically decay into pointers to their first elements.
int **getStuff() {
return myName; // 1
return &myName[0]; // 2
}

int **myName;
int **getStuff() {
int **array = new int*[5];
for (int i = 0; i < 5; i++)
{
int key = i;
array[i] = &key;
}
return array;
}

Steve Jessop, I think you meant:
int **myFunction() {
int **myArray = new int*[5];
return myArray;
}

This returns a heap array pointer (not pointer to its elements), testable and deletable. Nothing leaks.
template <class T>
T* newarray(int len)
{
T *a;
try
{
a = new T[len];
memset(a,0,len*sizeof(T));
return a;
}
catch (...)
{return 0;}
}
.
.
.
void foo()
{
float *f=0;
f=newarray<float>(1000000);
if(!f) return;
//use f
delete [] f;
}

Related

Passing pointer of multi-dimensional pointer array to a function

ok so suppose I have a function myFunction. Then in main i have a multi dimensional array of pointers. I want to pass a pointer to this array of pointers into myFunction. How would I do that? I know that If you want to pass an int to my function, one can write the function as
myfunct( int x) { ...}
What would that type of x be if I have to pass a pointer to an array of pointers? Thanks in advance :D
Typically you want to modify the elements of an array rather then the actual pointer. The actual pointer is given by malloc and if you change it, by writing directly to the value, it won't affect the memory allocation (except you might loose the initial pointer...).
This might be what you're looking for in a 2D array.
void myfunct(int** ptr,int items, int array_items)
{
//some code
}
int main(int argc, char *argv[])
{
const auto items = 5;
const auto array_items = 7;
int** multi_dimensional_array = reinterpret_cast<int**>(std::malloc(items * sizeof(int*)));
for (auto i = 0 ;i < items;++i)
{
multi_dimensional_array[i] = static_cast<int*>(std::malloc(sizeof(int) * array_items));
}
myfunct(multi_dimensional_array,items,array_items);
//deallocate
}
Wrap your multidimensional array inside a class. That way you can carry the data and dimensions in one block and passing it around is as simple as moving around any other class.
Remember to observe the Rules of Three, Five, and Zero, whichever best applies to how you store your array inside your class. std::vector is a personal favourite because it allows you to use the Rule of Zero.
For example:
#include <iostream>
#include <vector>
struct unspecified
{
};
template<class TYPE>
class TwoDee{
int rows;
int cols;
std::vector<TYPE> data;
public:
TwoDee(int row, int col):rows(row), cols(col), data(rows*cols)
{
// does nothing. All of the heavy lifting was in the initializer
}
// std::vector eliminates the need for destructor, assignment operators, and copy
//and move constructors. All hail the Rule of Zero!
//add a convenience method for easy access to the vector
TYPE & operator()(size_t row, size_t col)
{
return data[row*cols+col];
}
TYPE operator()(size_t row, size_t col) const
{
return data[row*cols+col];
}
};
void function(TwoDee<unspecified *> & matrix)
{
// does stuff to matrix
}
int main()
{
TwoDee<unspecified *> test(10,10);
function(test);
}
To directly answer your question, typically the type passed will be int * for a vector of int, and int ** for a 2D array of int
void myfunct( int **x)
{
x[2][1] = 25;
return;
}
If for some reason you wanted that to be an array of int pointers instead of int you need an extra *.
void myfunct( int ***x)
{
*(x[2][1]) = 25;
return;
}
Let me first try to interpret the exact type that you want to deal with. I suppose in your main function there is a "multidimensional array" which stores pointers for each element. As an example, let's say you have a 3-dimensional array of pointer to integer type.
Assume that you know the size of the array:
C style array will look like this:
int *a[4][3][2];
that means a is a 4x3x2 array, and each element in the array is a pointer to integer. So overall you now have 24 pointers to integer in total, as can be seen by testing the result of sizeof(a) / sizeof(int*) (the result should be 24). Okay, so far so good. But now I guess what you want is a pointer to the array a mentioned above, say b, so b is defined
int *(*b)[4][3][2] = &a;
Notice that although now b looks intimidating, in the end it is just a pointer which just stores an address, and sizeof(b) / sizeof(int*) gives 1 as the result. (The * inside parenthesis indicates b is pointer type, so b is a pointer to a "multidimensional array" of pointers to integer.)
Now to pass b to myFunction, just give the same type of b as argument type in the declaration:
void myFunction(int *(*x)[4][3][2]) {
// do something
}
And that's it! You can directly use myFunction(b) to invoke this function. Also, you can test that inside myFunction, x is still of the size of one pointer, and *x is of the size of 24 pointers.
*Note that since we are passing a pointer to array type into the function, the array-to-pointer decay does not apply here.
Assume you don't know the size of the array at compile time:
Say you have int N1 = 4, N2 = 3, N3 = 2; and you want to initialize a N1xN2xN3 array of pointer to integer, you cannot directly do that on the stack.
You could initialize use new or malloc as suggested in #Mikhail's answer, but that approach takes nested loops for multidimensional arrays and you need to do nested loops again when freeing the memory. So as #user4581301 suggests, std::vector provides a good wrapper for dynamic size array, which do not need us to free the memory by ourselves. Yeah!
The desired array a can be written this way (still looks kind of ugly, but without explicit loops and bother of freeing memory)
std::vector<std::vector<std::vector<int*>>> a (N1,
std::vector<std::vector<int*>> (N2,
std::vector<int*> (N3)
)
);
Now, b (the pointer to a) can be written as
auto *b = &a;
You can now pass b with
void myFunction(std::vector<std::vector<std::vector<int*>>>* x) {
// do something
}
Notice that the * before x means x is a pointer.

C++ Returning and Using a Pointer

Lets say for example I have a function like so, that is meant to return a pointer to an array.
int* oddInRange(int low, int high){
int odds[someLength];
// Some code to fill the array.
return *odds; // Is this the correct way to return?
}
Then once I've returned the pointer. How would I use it and get values from it?
int* testOdds = oddsInRange(1,10);
// What do I need to do with testOdds to get the values
// that were generated in the function above?
I understand that I probably don't need to use pointers here, but this it for the purposes of learning.
return *odds;
is an error since *odds evaluates to int, which does not match the return type. You can fix the syntax error by using
return odds;
but that will lead to problems at run time since the pointer will be invalid as soon as the function returns.
It's better to use std::vector and avoid all the problems with arrays.
std::vector<int> oddInRange(int low, int high){
std::vector<int> odds(someLength);
// Some code to fill the array.
return odds;
}
This will not work; your array is allocated on the stack, and as such is not available after the function exits.
In your case, you need to do one of two things - either create an array from the caller and pass it in, or dynamically allocate an array and return it. Take this as an example which dynamically allocates the array:
int* oddInRange(int low, int high){
int* odds = malloc(sizeof(int) * someLength);
// Some code to fill the array.
return odds; // Is this the correct way to return?
}
Or fills it in:
void oddInRange(int* odds, int low, int high) {
// Do stuff to odds
}
// And to call...
int* myArr = malloc(sizeof(int) * someLength);
oddInRange(myArr, 1, 2);
Anyway, if we ignore the stack allocation problem for a second, your code is still wrong. You want to get a pointer to the array. In C, an array variable can decay to a pointer implicitly, so you don't need to use & or * to get a pointer to the array, you just use the name. You could also take the address of the first element. Take these examples:
int myArray[10];
int* myArrayPtr = *myArray; // What you had. Incorrect.
int* myArrayPtr = myArray; // OK - arrays decay to pointers to the first element.
int* myArrayPtr = &myArray[0]; // Also OK.

C++ Pointer and 2d array outputting

I'm new to C++ and still really confused about how 2d arrays work with pointers. If I have this (in example format):
int* anarray = anarrayfiller();
for (int a=0;a<10;a++) {
for (int b=0;b<10;b++) {
cout<<(char)anarray[a][b]; //Here's the error mentioned below
}
cout<<"\n";
}
//Later, outside main
int* anarrayfiller() {
int anarray[10][10];
//Populated here
return &anarray;
}
This produces an error under b in the cout<< line:
"Expression must have pointer-to-object type"
I would just check how to search through 2d arrays, and I found this:
A pointer to 2d array
Which suggests that actually this pointer points to the array of ints inside anarray[0], and if that's the case, I must be missing something in terms of returning pointers - wouldn't I then have to return a pointer to a 2d array of pointers that each points to a specific int from anarray? I'm pretty confused here. How do pointers work with 2d arrays?
You have a few errors here:
You return a pointer to a local variable. After the function returns the stack area previously occupied by that variable no longer exist, or is used by the next function.
You return a pointer to an integer, while you have a two-dimensional array. The closest would be a pointer-to-pointer.
You access thing single-pointer as though it was a double-pointer (pointer-to-pointer or pointer-to-array or array-or-arrays), but it's not. That's the reason you get errors at the pointed to line.
But you can't use pointer to pointer, as the memory layout of an array-of-arrays (a two-dimensional array) is different from a pointer-to-pointer. See e.g. this old answer of mine for an explanation of why.
This can be solved most easily by creating the array dynamically on the heap, as a pointer-to-pointer:
int **anarrayfiller()
{
int **anarray = malloc(sizeof(int *) * 10);
for (int i = 0; i < 10; ++i)
{
anarray[i] = malloc(sizeof(int) * 10);
/* Populate here */
}
return anarray;
}
As you tagged your question as C++, you should actually avoid plain arrays or pointers in favor of either std::vector (if you need to add dynamically) or std::array (if you have a fixed compile-time size):
std::array<std::array<int, 10>, 10> anarrayfiller()
{
std::array<std::array<int, 10>, 10> anarray;
// Populate arrays
return anarray;
}

How do I pass a reference to an array, whose size is only known at run-time, as a function parameter?

I have an array that is being dynamically created based on user input, and I need to pass that array to a function where it will be manipulated and the results passed back out to the original array. When I try to use
void MyFunction(int (&MyArray)[])
my compiler complains that it doesn't know how big the array is.
You can't. You could use a std::vector though.
You can give a pointer to the first element of the array + a second parameter holding the size of the array.
If it's just an array, why not pass the array itself and its size as a second parameter? (by passing the array as an int* or int[], same thing as far as C++ is concerned).
As the value of the variable containing your array is only the pointer to the first element of your array, you don't end up killing your runtime by copying the contents of the array, but just a pointer which is as small as you can get in this case.
void MyFunction( int MyArray[], int size ) { /* edit the array */ }
int main() {
// read nrElements
// ...
// create the array
int *a = new int[nrElements];
// populate it with data
// ...
// and then
MyFunction(a, nrElements);
}
You should use a std::vector only if you want to resize the array in your function (e.g. add new elements to it), but otherwise you can just stick to this approach because it's faster.
Btw, the only case you would need a reference to an array is if you want to change the value of the variable you pass in when you call the function, as in, make it point to a different array. Like in:
void createMyArray(int* &array, int nrElements) {
array = new int[nrElements];
for (int i = 0; i < nrElements; ++i) {
array[i] = 0;
}
}
int *a = (int []) {1, 2, 3};
std::cout << a[0] << std::endl; // prints 1
createMyArray(a, 10);
// now a points to the first element of a 10-element array
std::cout << a[0] << std::endl; // prints 0
But you said the array is already created before providing it to the function, there's no point in using references.

Passing by reference 3-Dim Fixed length array

Can anyone hint on how to pass by reference an array of the kind
int array[2][3][4];
so that I may save his pointer in order to use and modify the array?
Like, if I were speaking about a single integer:
// Scope 1
int a = 3;
increment(&a);
// End Scope 1
// Scope 2
int *pa;
void increment(int *tpa) {
pa = tpa; *pa++;
}
// End Scope 2
Thanks a lot and best regards.
If you really want to pass the array by reference, you can do so:
void f(int (&a)[2][3][4]) { }
In C, which doesn't have references, you can pass the array by pointer (this works in C++ too, of course):
void f(int (*a)[2][3][4]) { }
C++:
void f(int (&array)[2][3][4])
{
}
C: There are no references in C
Note that no matter how you pass the array, via reference or not, the array is not going to be copied, so you'll get the original pointer. You can pass this array also like this:
void f(int array[][3][4])
{
}
Thanks to everyone who participated in this! sskuce provided a very good solution, taking advantage of a "container". I had thought about this but didn't really like the extra stuff.
I realized after a little jumbling that James McNellis had given the answer all along. So... here's the solution I prefer with no containers and no indexes arithmetic (mind the parenthesis):
void Scope1()
{
int array[2][3][4];
Scope2(&array);
}
int (*pArray)[2][3][4];
void Scope2(int (*tpArray)[2][3][4]))
{
pArray = tpArray;
(*pArray)[0][0][0] = 3;
}
Thanks again to everyone.
Edit: I'm keeping my original answer below, as I believe it's necessary for folks to understand how arrays are actually passed to functions and how they're layed out in memory, but on further reflection I think there is a simple and correct way to get what you want done.
Encapsulate the array within a struct, e.g.
typedef struct ArrayHolderStruct{
int array[2][3][4];
} ArrayHolder
//...
//scope 1
ArrayHolder thingy;
thingy.array[0] = something;
//other initialization.
F( &thingy );
//...
//scope 2
ArrayHolder *pa;
void F ( ArrayHolder *p ){
pa = p;
p->array[0][1][2] = 42;
}
//Call F first to set pa.
void G(){
pa->array[0][1][2] = 6 * 9; // if pa = &thingy, thingy will be modified.
}
The struct will allow you to maintain layout information about the encapsulated array, and you don't have to worry about nasty index arithmetic.
-----OLD ANSWER-----
Passing a reference to an array is not useful, unless you want to change the size or layout of the array (which you can't do with statically sized arrays anyway). You'll get a reference (or pointer) to the elements of the array even if you pass the array by "value". That is to say, if you declare your function:
void f ( int a[2][3][4] ){
a[0][1][2] = 42;
}
and call it like f( array ) when f exits, array[0][2][2] will have been set to 42, even though you didn't pass a "reference" to array into the function.
If you want to save a pointer to the array for later use in a library function, etc, you could do something like:
//scope 2
int * pa;
void f ( int a[2][3][4] ){
pa = &a[0][0][0];
}
It gets tricky at this point - you have to know how pa is layed (laid?) out in memory. I think C has standardized on 'row major order', so the array should be layed out in memory like:
a[0][0][0] a[0][0][1] a[0][0][2] a[0][0][3] a[0][1][0] ... a[0][2][3] a[1][0][0] a[1][0][1]... a[1][2][3]
So, to get at an element at index [n][j][k], you have to do something like:
pa[n * 12 + j * 4 + k] = something;
Basically, multiply each index by the number of elements that can be referenced by an index of that order, e.g. each k index points to exactly one element given a fixed j and n index, each j index can point to 4 elements given a fixed n index, and each n index can point to one of 12 (because 12 = 3 * 4) elements.
Like I said, it's tricky. See the wikipedia articles on Array Data Structures and Row-major order to get a better understanding of how these things are layed out.