C++ Pointer and 2d array outputting - c++

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;
}

Related

Cannot convert double [] [] to double **

I ve got a function that takes 3 parameteres, first one is **double.
normalizeDataZeroMeanUnitSD(double ** trainingActions, int numberOfTrainingActions, int descriptorDimension)
When I call it from main, I am trying to use normalizeDataZeroMeanUnitSD(data, 681, 24); however, I am receiving
cannot convert parameter 1 from 'double [681][24]' to 'double **'
This is how I construct the data array:
fstream infile;
infile.open("gabor\\Data.txt");
double data[681][24];
while (!infile.eof())
{
for(int j=0;j<681;j++)
{
for(int k=0; k<24;k++)
{
infile >> data[j][k];
}
}
}
infile.close();
Is there a way to do the same using **data?
The error is pretty clear: Datatype double [681][24] is not the same as double **. While it's true that double[681] can decay to a pointer to its first element (thus, double*), that does not imply that double[681][24] can decay to double**.
Think about it this way: double** implies a pointer to many pointers. But double[][] does not have ANY pointers in it. At best, an array of ANY dimensions still only has, at very most, one pointer: to the beginning of its contiguous storage.
You could use a template:
template<std::size_t M, std::size_t N>
void normalizeDataZeroMeanUnitSD(double (&trainingActions)[M][N], int descriptorDimension)
{
for( std::size_t m = 0; m < M; ++m )
{
for( std::size_t n = 0; n < N; ++n )
{
trainingActions[m][n] = ...;
}
}
}
But beware of code bloat if you call this with many differently sized arrays.
Use any of the following declarations. Both are equivalent.
NormalizeDataZeroMeanUnitSD(double trainingActions[][24], int numberOfTrainingActions, int descriptorDimension)
NormalizeDataZeroMeanUnitSD(double trainingActions[681][24], int numberOfTrainingActions, int descriptorDimension)
When you declare a 2D array it takes up contiguous memory locations. So you need to specify at least the number of columns (in case of row major architecture).
For row major and column major definitions, have a look at this.
For your edited question, yes you can declare using **data. Dynamically allocate the data array. But remember to free it when you're done with it.
double **data=new double*[681];
for (int i=0;i<681;i++)
{
data[i]=new double[24];
}
//do what you want to do
for (int i=0;i<681;i++)
{
delete [] data[i];
}
delete [] data;
Now your function prototype can be like void func(double **pp) because data is a pointer not a 2D array.
A 2d array is a continuous area of storage. The function expects a pointer to pointers. These are incompatible.
The function expects an array of pointers to arrays; you have an array of arrays. Some options are:
change the function to take a more friendly type, perhaps double* pointing to the first element of a contiguous 2-dimensional array; or
build a separate array of pointers pointing to each row of your 2-dimensional array; or
restructure your data into an array of pointers to arrays.
Here is a constructive answer for how to make it work.
Basically, you need to generate an array that has pointers to each 1D slice of your 2D array.
double data[N][M] = {...};
double *dataPtrs[N];
for(size_t n=0; n<N; ++n) {
dataPtrs[n] = data[n];
}
normalizeDataZeroMeanUnitSD(dataPtrs, N, M); // order of N and M might be wrong
Yay, I get to rant about this again.
In C++, despite having similar syntax, 2D arrays are NOT jagged arrays. 2D arrays (double foo[681][24]) are allocated contiguously in memory. When you deference a 2D array (foo[j][i]) it actually does *(foo+24*i+j). This is all done under the hood. The sizeof(foo)==sizeof(double)*681*24.
Jagged arrays are (double** bar;). This is a bunch of different arrays: first, you allocate an array of pointer, 268 members long. Each pointer will point to an array of doubles, 24 elements long. Bar is just a pointer, so sizeof(bar)==sizeof(void*).
More annoyingly, 2D arrays (or a static array of any dimension) behave the opposite of all other types in C++ in the following reguard: they are passed implicitly by reference, causing the weird phenomenon below.
void foo(double bar[24][24]) { std::cout << sizeof(bar) << std::endl;}
int main() {
double test[24][24];
std::cout << sizeof(test) << std::endl;//returns sizeof(double)*24*24
foo(test);//returns sizeof(void*), implicitly passed by reference, opossite of the rest of c++!
double[][] is not the same thing as double**.
double** is a pointer to pointers.
double[][] is a 2-dimensional array allocated as continuous storage.
In order to pass a "2-dimensional array" to the function, you need to create an array of pointers to arrays. For example:
double* array_2d[681];
for(unsigned int i=0; i<681; ++i) {
array_2d[i] = new double[24];
}
normalizeDataZeroMeanUnitSD(array_2d, 681, 24);
Remember to later delete[] each element of array_2d!
Better yet, change normalizeDataZeroMeanUnitSD to take a reference to std::vector<std::vector<double>>, and you no longer have to worry about memory management, nor passing the correct dimensions to the function.

initialize an int[][] with new()

I am a c++ newbie. While learning I came across this.
if I have a pointer like this
int (*a)[2][3]
cdecl.org describe this as declare a as pointer to array 2 of array 3 of int:
When I try
int x[2][3];
a = &x;
this works.
My question is how I can initialize a when using with new() say something like
a = new int [] [];
I tried some combinations but doesn't get it quite right.
Any help will be appreciated.
You will have to do it in two steps - first allocate an array of pointers to pointers(dynamically allocated arrays) and then, allocate each of them in turn. Overall I believe a better option is simply to use std::vector - that is the preferred C++ way of doing this kind of things.
Still here is an example on how to achieve what you want:
int a**;
a = new int*[2];
for (int i =0; i< 2;++i){
a[i] = new int[3]
}
... use them ...
// Don't forget to free the memory!
for (int i = 0; i< 2; ++i) {
delete [] a[i];
}
delete [] a;
EDIT: and as requested by Default - the vector version:
std::vector<std::vector<int> > a(2, std::vector<int>(3,0));
// Use a and C++ will take care to free the memory.
It's probably not the answer you're looking for, but what you
need is a new expression whose return type is (*)[2][3] This
is fairly simple to do; that's the return type of new int
[n][2][3], for example. Do this, and a will point to the
first element of an array of [2] of array of [3] int. A three
dimensional array, in sum.
The problem is that new doesn't return a pointer to the top
level array type; it returns a pointer to the first element of
the array. So if you do new int[2][3], the expression
allocates an array of 2 array of 3 int, but it returns
a pointer to an array of 3 int (int (*a)[3]), because in C++,
arrays are broken (for reasons of C compatibility). And there's
no way of forcing it to do otherwise. So if you want it to
return a pointer to a two dimensional array, you have to
allocate a three dimensional array. (The first dimension can be
1, so new [1][2][3] would do the trick, and effectively only
allocate a single [2][3].)
A better solution might be to wrap the array in a struct:
struct Array
{
int data[2][3];
};
You can then use new Array, and everything works as expected.
Except that the syntax needed to access the array will be
different.

How to pass a two dimensional array to a function in c++

I am trying to pass an array (2d) to a function as an parameter.
I have a code as follows:
int main()
{
float T[100][100];
void set_T(float T[][]);
}
void set_T(float T1[][])
{
for (int i =0 ; i<90;i++)
{
for(int j =0 ;j <90;j++)
{
T1[i][j] = 3;
}
}
}
I am not sure how to pass array to a function ...I am getting lot of errors. Can any one help please.
There are two issues here:
C does not support 2D arrays, only arrays of arrays or arrays of pointers to arrays, neither of which is quite the same thing as a 2D array
C does not allow passing arrays to functions as arguments, only pointers into arrays (generaly, you use a pointer to an array's 0th element, since that's what the array's name ends up being so indexing off of such a pointer looks just like an array access)
So because of the first problem, you have to decide how you're going to represent a 2D array -- either an array of arrays, or an array of pointers to arrays. If you go the first route, your code ends up looking like:
void set_T(float (*T1)[100]) {
... do stuff with T1[i][j] ...
}
int main() {
float T[100][100];
set_T(T);
}
Here, you've declared T to be an array of 100 arrays of 100 floats, and set_T takes a pointer to arrays of 100 floats as its argument. You pass 'T' directly to set_T, as the language treats array names as pointers to their 0th element.
If instead you want to use an array of pointers to arrays, you end up with something like:
void set_T(float **T1) {
... do stuff with T1[i][j] ...
}
int main() {
float *T[100];
float space[100*100];
for (int i = 0; i < 100; i++)
T[i] = space + i*100;
set_T(T);
}
The disadvantage here is that you need to allocate space for all of the second-level arrays and manually initialize all the first-level pointers to point at them. The advangtage is that the sizes of the second level arrays is not part of the type of the argument passed to set_T, so you can more easily deal with variable-sized arrays.
Of course, if you're really using C++ and not C, you should not be using C arrays at all -- you should be using std::vector or std::array instead -- both of which share the C array 1D only issue, so you need a vector of vectors or an array of arrays (or conceivably a vector of arrays or an array of vectors)
void set_T(float (&T)[100][100]);
Just call it like this:
int main ()
{
float T[100][100];
set_T(T);
}
And as #suddnely_me said, the type of T1 in the function declaration need to be float**.

How can I return a pointer to an array in C++?

Here is my simple code
arrayfunc() should store some numbers in an array, and return the pointer of this array
to main function where the content of the array would be printed
What is the problem with my code?
It only returns the pointer to the first element of the array
Any help will be appreciated.
Thanks in advance.
#include <iostream>
using namespace std;
//The definition of the function should remain the same
int* arrayfunc()
{
int *array[10];
array[0] =new int;
array[1] =new int;
array[2] =new int;
array[3] =new int;
*array[0]=10;
*array[1]=11;
*array[2]=12;
*array[3]=13;
return *array;
}
int main()
{
for(int i=0;i<4;i++)
cout<<*(arrayfunc()+i)<<endl;
return 0;
}
(1) You should allocate your array with new if you want to return it: int* array = new int[10]; [assuming here you want array of ints and not array of int*'s]
(2) to return the pointer to the first element in the array, use return array and not return *array
(3) your array is array of pointers, and not array of ints.
Your array is allocated on stack, so as soon as the function returns, it's freed. So you want to return a pointer to a dead memory.
But you are not doing that, you are just returning the valid (copy of) value of the 0th array item.
So, what you have to do:
The best idea would be to switch to stl containers. You should be using std::vector or something like that.
If you stick to the idea of manual memory management, you have to allocate the array on heap, return it from the function, and perhaps deallocate it in the caller.
Edit:
basically you want the following:
using namespace std;
vector<int> arrayfunc()
{
vector<int> v;
v.push_back(10);
...
return v;
}
...
vector<int> result = arrayfunc();
cout << result[0] << ...
This would be the right C++ way.
(Nitpicking:) You don't need to care about copying the vector, because of the RVO used by all modern C++ compilers.
Allocating an array on heap should be simple, too:
int* array = new int[4];
array[0] = 10;
...
return array;
...
int* array = arrayfunc();
...
delete[] array;
But I would strongly advise to take the former approach (with vector).
This codes seems wrong to me in several levels.
Never return an internal variable of a function. The variable array is only defined in the function, so it should never be returned outside.
Why do you allocate each int by itself with new? I would allocate the entire array at once. If you know the array length and it's constant, consider having it defined statically.
http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx
Just try return array; instead of return *array;

Pointer Pointer Methods 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;
}