Issue in Passing a 2-D array - c++

I read how to pass 2-D arrays in a function as a parameter and tried to implement the same. There are two problems which I encountered:
1) The first line of the output of the code contains garbage value.
2) What does the line ((arr + in) + j) actually do ? I mean, Why can't we do something like ((arr + i) + j) to access arr[i][j] ?
I also tried passing the matrix using parameter int **arr and then tried printing the value as arr[i][j] but there was no output.
Here is the output that I get:-
Enter number of nodes: 4
0167772161878012032-1
0000
0000
0000
And here is my code :-
#include <iostream>
using namespace std;
void show(int* arr, int n)
{
int i, j;
for(i = 0; i < n; ++i)
{
for(j = 0; j < n; ++j)
{
cout << *((arr + i*n) + j);
}
cout << endl;
}
}
int main()
{
int n, i, j;
cout << "Enter number of nodes: ";
cin >> n;
int arr[n][n] = {{0}}; //Will initialize all elements in the matrix with 0.
show((int*)arr, n);
}

The biggest problem here is that you are using C and not C++.
To avoid people gasping and starting religious or political discussion, let's nail it down to:
VLAs (Variable Length Arrays) are not allowed in C++.
Additionally, you should never use raw pointers for owned memory and no pinter arithmetic.
And then the main topic:
Issue in Passing a 2-D array
The used syntax for passing arrays to function is wrong. In C++ arrays can be passed by reference or by pointer. Please see:
void function1(int(&m)[3][4]) // For passing array by reference
{}
void function2(int(*m)[3][4]) // For passing array by pointer
{}
int main()
{
int matrix[3][4]; // Define 2 dimensional array
function1(matrix); // Call by reference
function2(&matrix); // Call via pointer
return 0;
}
Of course we can do all kind of dirty designs with pointers. Even accepting pointer decays. But we should not do it.

Variable length arrays is not a standard C++ feature.
Nevertheless you passed to the function a pointer to the first element of a two-dimensional array.
Each "row" of the two-dimensional array has n elements. So if you have a pointer to the first element of the first row then to get the pointer to the first element of the second row you have to write
arr + n
If you want to get the first pointer to the i-th row of the two-dimensional array you have to write
arr + i * n
To get pointer to an element within the row you have to write
( arr + i * n ) + j
that is the same as
arr + i ( n + j
to get the element pointed to by the pointer you have to dereference the pointer
*( arr + i * n + j )

Related

Inserting a Integer Array into a Pointer Array?

Can someone tell me how this compiles. How can you assign an integer array element to a pointer array element? The weird this is that the output suggests that nums[i] is an integer rather than a pointer, however nums was defined as a pointer.
#include <iostream>
int main() {
int n;
int *nums = NULL;
nums = new int[n]; // Assign pointer nums to a address in heap allocated for a integer array of n-elements.
n=5;
int Array[n] = {5,4,3,6,8};
for(int i=0; i<n; i++)
{
nums [i] = Array[i];
std::cout << nums[i] << " , " << &nums[i] << std::endl;
}
delete []nums;
return 0;}
I get the following output:
5 , 0x786cd0
4 , 0x786cd4
3 , 0x786cd8
6 , 0x786cdc
8 , 0x786ce0
Thanks for any help
How can you assign an integer array element to a pointer array element?
nums is a pointer to a dynamic array of int elements, in this case to the 1st int in the array. Dereferencing nums[i] yields an int& reference to the ith element in the array.
Array is a fixed array of int elements. When a fixed array is accessed by its name, it decays into a pointer to the 1st element. So, dereferencing Array[i] also yields an int& reference to the ith element in the array.
Thus, nums[i] = Array[i]; is simply assigning an int to an int. Nothing weird about that.
the output suggests that nums[i] is an integer rather than a pointer
That is correct, it is.
however nums was defined as a pointer
That is also correct. It is a pointer to an int, in this case the 1st int in the dynamic array.
Also, on a side note, your code has undefined behavior because n is uninitialized when used to allocate nums, and int Array[n] is non-standard behavior since n is not a compile-time constant.

Passing 2D array of const size

How should an array of constant size:
const int m = 5, n = 3;
int arr[m][n];
be passed to a function in a way which is both C89 and C++-compatible?
void func(const int m, const int n, int arr[][n]) { }
isn't valid C++ (giving errors such as "A parameter is not allowed" and "Variable 'n' was not declared in this scope"), even though the size of arr is determinate at compile-time. (It is valid C, however.) #defineing m and n works but is not preferred due to scope issues. Passing a pointer to the first element of the array leads to ugly code in the function body.
Feel free to take a look at this FAQ for context.
In C++, you can pass an array to a function with full type information intact by utilizing a template and an array reference function argument:
template <unsigned M, unsigned N>
void func (int (&arr)[M][N]) {
//...
}
The function prototype you are using is using a C99 feature called VLA to provide a dynamic binding of the array dimension. This is not a C++ feature, although some C++ compilers will allow it as an extension to the C++ language.
The C-FAQ was written before C99 was ratified, so the variable length array feature was not yet a standard feature of C. With a modern C compiler with VLA support, the function prototype you provided works just fine.
There is another alternative to use if you have an older compiler for which VLA support is not available. That is to treat the 2-D array as a flattened 1-D array, and use manual calculations to index the correct integer:
void func(const int m, const int n, void *p) {
int *a = p;
int i, j;
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
printf(" %d", a[i*n + j]);
}
puts("");
}
}
Then you call func(m, n, arr). In side the function, the expression
a[i*n + j]
steps over n ints i times, then steps over j ints. Since each row is n ints long, the calculation returns the ith row and the jth column, which corresponds precisely to arr[i][j].
I have tried this code:
void func(const int m, const int n, int arr[][n])
{
printf("%d\n", arr[4][2]);
}
int main()
{
const int m = 5, n = 3;
int arr[m][n];
arr[4][2] = 10;
func(m, n, arr);
}
and this work with no warnings
Your array arr[m][n] is not constant. However you have constant variables M and N. You should also define the arr[m][n] as a constant and not just an int array.
You may want to consider dynamicaly allocating your array so that you can just pass the pointer address down.
const int m = 5, n = 3;
int i = 0;
int* *arr; //Pointer to an integer pointer (Note can also be int **arr or int** arr)
arr = malloc(sizeof(int*)*(m+1)); //I add one because I am assuming that 'm' does not account for the terminating null character. But if you do not need a terminating null then you can remove this and the perantheses around the 'm'.
for(i = 0; i < m; i++)
{
arr[i] = malloc(sizeof(int*)*(n+1)); //Same as before
}
The inital malloc() call allocates memory for an array of integer arrays or said in another way, it allocates a pointer to a series of other pointers. The for loop will allocate an integer array of 'm' size for each element of the original array or said another way it will allocate space for every pointer address pointed to by the original pointer address. I left out error checking in order to simplfy my example but here is the same example with error checking.
const int m = 5, n = 3;
int i = 0;
int* *arr = NULL;
if((arr = malloc(sizeof(int*)*(m+1))) == NULL)
{
perror("ERROR(1): Failed to allocate memory for the initial pointer address ");
return 1;
}
for(i = 0; i < m; i++)
{
if((arr = malloc(sizeof(int*)*(m+1))) == NULL)
{
perror("ERROR(2): Failed to allocate memory for a subsequent pointer address ");
return 2;
}
}
Now that you have dynamicaly allocated your array you can just pass the pointer address.
int* *arr in the following the way.
void fun(const int n, const int m, int* *arr) {}
Also you don't necessarily have to keep track of the size of your arrays if the sizes are constant and if you use null terminated arrays. You just have to malloc the array using the constant integer variable's actual value and then check for the terminating null byte when iterating threw the array.
int* *arr = NULL;
if((arr = malloc(sizeof(int*)*6)) == NULL)'m'+1 = 6;
{
perror("ERROR(1): Failed to allocate memory for the initial pointer address ");
return 1;
}
for(i = 0; i < m; i++)
{
if((arr = malloc(sizeof(int*)*4) == NULL)//'n'+1 = 4
{
perror("ERROR(2): Failed to allocate memory for a subsequent pointer address ");
return 2;
}
}
You can then display the entire two dimensional array in the following way. Note that '\000' is the octagonal value for a null byte(00000000).
int i, j;
for(i = 0; arr[i] != '\000'; i++)
{
for(j = 0; arr[i][j] != '\000'; j++)
{
printf("%i ", arr[i][j]); //Prints the current element of the current array
}
printf("\n"); //This just ends the line so that each of the arrays is printed on it's own line.
}
Of course the above mentioned loops would have the same result as the following.
int i, j;
int m = 5;
int n = 3;
for(i = 0; i < m; i++)
{
for(j = 0; i < n; j++)
{
printf("%i ", arr[i][j]); //Prints the current element of the current array
}
printf("\n"); //This just ends the line so that each of the arrays is printed on it's own line.
}
Which means, in most situations there is no need for keeping track of an array's size but there are situations in which it is necessary. For example if one your arrays could possible contain a null byte other than the terminating null byte. The new null byte would shorten the array's size to the index of the new null byte. If you have any questions or comments feel free to comment below or message me.
The problem here is the "missing" support for dynamic arrays in C++.
const int m = 5, n = 3;
int arr[m][n];
Works since m and n are compile time constant and accessible directly at the declaration of the array.
void func(const int m, const int n, int arr[][n]) { }
The compiler handles your function regardless of where it is called in first place.
Therefore n is unknown/variable and thus prohibited as a array dimensionality.
The following example won't work too because of the very same reason:
void foo (const int n)
{
int arr[n]; // error, n is const but not compile time constant
}
int main (void)
{
foo(4);
}
jxh answered what to do about it.

reverse c++ array

my aim is to reverse an array 3,12,2,1 to 1,2,12,3. when i run this code i get garbage before my actually result. i can't seem to see where the problem is please assit
#include<iostream>
using namespace std;
int rev (int arr[], int a){
//int r;
for(int i =a-1; i>=0; i--){
cout<<arr[i]<<" ";
}
return 0;
}
int main(){
int arr[] = {6,41,12,5,2};
cout<<"The rev of {6,41,12,5,2}"<<endl;
cout<<rev(arr, sizeof(arr))<<endl;
system("pause");
return 0;
}
Use sizeof(arr)/sizeof(arr[0]) instead of sizeof(arr).
sizeof(arr) gives the total size of the array. sizeof(arr[0]) is the size of one array element (all elements have the same size). So sizeof(arr)/sizeof(arr[0]) is the number of elements.
An optimized answer to the question would be using reverse () from STL if you are allowed to use it:
std::reverse
http://www.sgi.com/tech/stl/reverse.html
int main()
{
int arr[] = {6,41,12,5,2};
cout<<"The rev of {6,41,12,5,2}"<<endl;
reverse(arr, arr + 5);
copy(arr, arr + 5, ostream_iterator<int>(cout, ", "));
}
sizeof return the size in bytes. In your example, if sizeof(int) = 4, it returns 20.
Because you're using an array, you have to keep the size of the array handy as well. sizeof computes the size of a value in memory, in this case the size of all the memory used to represent arr. You can do sizeof(arr)/sizeof(int) to get the number of elements in an array. This makes sense because it's taking the total size of the array and dividing it by the size of an element in the array. Beware however that this only works for arrays (int arr[4] = {6,41,12,5,2};). If it's a pointer to a heap-allocated array via something like int* i = new int[4]; you'll need to keep the size of the array hanging around.
Also, you're calling your reverse function from within a cout<< call, which will print the function's return value (in this case it's hard-coded to 0).
It also turns out there is a function in the C++ standard library (std::reverse) that can do this.
If I may speak subjectively and in an off-topic manner about your approach, it is very un-C-like. My personal favorite way to reverse an array goes like this:
void reverse(int *a, int n)
{
int *p = a, *q = a + n - 1;
while (p < q)
{
int swap = *p;
*p++ = *q;
*q-- = swap;
}
}
// Usage:
int a [] = { /* ... */ };
reverse(a, sizeof(a)/sizeof(*a));
Of course, since your question is tagged c++, there's always std::reverse().
Sizeof operator return the one extra (arrayLength + 1) here 6 will return when passs 6 it store in a when a-1 you get 5 but array index start from 0 length-1 that from 0 to 4 here i pointing to index 5 that is not last element last+1 that why you got garbage value

How do I treat a pointer as a multi array?

I have this loop which gives seg. fault.
s->c = malloc(width * height * sizeof(double));
if (s->c == NULL) { puts("malloc failed"); exit(1); }
for (int n = 0; n < width; n++) {
for (int m = 0; m < height; m++) {
d = (&s->c)[m][n];
printf("d %f\n", d);
printf("m %i\n", m);
printf("n %i\n", n);
}
}
Inside s->c is:
double* c;
When executed it just outputs:
d 27.000000
m 0
n 0
and then seg. fault.
It worked when I treated the s->c as a 1D array, but I would really like to treat it as a 2D array.
Is that possible, when the c pointer is in a struct?
If so, is (&s->c)[m][n] then the correct way to access the elements?
Sandra
The problem is that the compiler doesn't know the dimensions of your matrix.
When you have: double tab[m][n] you can access the element tab[row][col] as *(tab + (row * n) + col)
In your case you only have double *tab; that can be considered as the pointer to the element tab[0][0] with no information on the matrix dimensions and the compiler can't compute the right address.
You could compute the address yourself (for example using a macro) but would lose the nice tab[x][y] syntax.
I`m surprised it compiles. You should have received at least a warning about implicitly casting a double to a pointer.
I'm very surprised it even compiles. Apparently c is a double*, so (&s->c)[m] is the m'th double. Now, double doesn't have an operator[], so I don't see how the [n] part in (&s->c)[m][n] can be legal.
Presumably, you have declared c differently. There are different solutions: a pointer to a pointer, an pointer to an array of doubles, an array of pointers to doubles, etcetera. All might work, if the allocations match the declaration. In your case, the allocation will not match the declaration.
The correct way to access the array elements is
d = s->c[m * width + n];
Is that what you mean by treating it as a 1D array?
Access the elements using
double d = s->c[m*width+n];
Perhaps through an inline function, to avoid unexpected behaviour.
The compiler does not know about the width of your intended 2D array. It might possibly interpret (&s->c)[m][n] as s->c[m+n], or as something quite different.
Short answer: you can't treat it as a 2D array, at least not in the way you expect.
The reason writing
(&s->c)[m][n]
doesn't work can be shown as follows. Assume the address of s->c is 0x00080004, and the address of the dynamically allocated memory pointed to by s->c is 0x00001000.
The expression (&s->c)[m][n] is evaluated as *(*(&s->c + m) + n);
The expression &s->c evaluates to 0x00080004;
The expression (&s->c + m) evaluates to 0x00080004+m;
The expression *(&s->c + m) evaluates to the value of whatever is pointed to by 0x00080004+m. If m is 0, then 0x00080004+m points to 0x00001000, which is the address of your dynamically allocated memory (*(&x) == x). If m is any other value, then 0x00080004+m points somewhere random;
The expression (*(&s->c + m) + n) evaluates to whatever 0x00080004+m points to offset by n. If m is 0, then the value is 0x00001000+n, or an offset into your dynamically allocated memory. If m is not 0, then the value is something random;
The expression *(*(&s->c) + m) + n) attempts to dereference the above value. If m is 0, then the result is the value of an element in the dynamically allocated array. If m is not 0, then the result is ... something else. In your case, a segfault.
If you want to dynamically allocate a 2D array, you have to use a pointer to a pointer and allocate it in steps, like so:
struct {
...
double **c;
...
} *s;
...
/**
* Notes: type of s->c is double **
* type of *(s->c) and s->c[i] is double *
* type of *(s->c[i]) and s->c[i][j] is double
*/
s->c = malloc(sizeof *(s->c) * rows);
if (s->c)
{
for (i = 0; i < rows; i++)
{
s->c[i] = malloc(sizeof *(s->c[i]) * columns);
if (s->c[i])
{
// initialize s->c[i][0] through s->c[i][columns-1]
}
}
}
If you want to allocate s->c as a 1D array, then you can define a macro that does the job for you (but you need to know the second dimension):
#define AR(M, X, Y) ((M)[(Y) + dimy * (X)])
I'm surprised nobody mentioned boost::multi_array_ref:
#include <iostream>
#include <boost/multi_array.hpp>
int main()
{
int rows = 4, cols = 3;
// Allocate one big block of contiguous data for entire multi-array
double* arrayData = new double[rows*cols];
if (arrayData)
{
boost::multi_array_ref<double, 2>
arrayRef(arrayData, boost::extents[rows][cols]);
for (int row = 0; row < rows; ++row)
{
for (int col = 0; col < cols; ++col)
{
arrayRef[row][col] = row*cols + col;
std::cout << arrayRef[row][col] << " ";
}
std::cout << std::endl;
}
}
delete [] arrayData;
}
You can also just use boost::multi_array and resize it dynamically:
boost::multi_array_ref<double, 2> marray;
marray.resize(boost::extents[rows][cols]);

Passing a variable of type int[5][5] to a function that requires int**

I'd like to test a function that takes runtime-allocated multidimensional arrays, by passing it a hardcoded array.
The function has a signature of void generate_all_paths(int** maze, int size) and the array is defined as int arr[5][5] = {REMOVED}.
I'm not exactly sure how to properly coerce the array for the function (or if that is impossible).
This multi dimensional array topic unfortunately confuses so many C++ programmers. Well, here is the solution:
void generate_all_paths(int (*maze)[5], int size);
That is what the function declaration has to look like. An alternative, but fully equivalent is
void generate_all_paths(int maze[][5], int size);
Both are creating a parameter that is a pointer to an array of 5 integers. You can then pass your array of arrays of 5 integers to that function:
generate_all_paths(arr, 5);
Because your array's first element is an array of 5 integers, it will be converted automatically (implicitly) to a pointer to that first element when passed to that function.
In the comments, you have shown you are bound to an int**, because both your inner and outer dimension must have runtime values. A multi-dimensional array can not be used anymore. What you can do for testing purposes then is to create an array of pointers like this:
int store[5 * 5] = { ..... };
int *arr[5] = { store, store + 5, store + 10, store + 15, store + 20 };
Then, actually, you can have your function accept a int**. As the first element of you array then is a int*, it will be converted to a int** automatically. Another way of doing this is keeping the data in the 2 dimensional array, but just creating a "view" structured of pointers to that array:
int *arr[5] = { store[0], store[1], store[2], store[3], store[4] };
Where store is your int[5][5] array. Since store[n] accesses the n'th sub-array of that two-dimensional array and the element type of it is int, the pointer-converted type of it is int*, which will be compatible again.
You can write:
void display(char **a)
And then use a[i][j] to refer to elements in it.
The declaration char ** means "pointer to pointer to integer". To break it down into steps:
char *b = a[i];
That gets you a pointer to the first element of the i'th array in the array-of-arrays.
char c = b[j];
That gets you the j'th element in the array b.
The next problem you'll have is of allocating such an array-of-arrays.
char **arrayOfArrays = new char *[10];
for (int n = 0; n < 10; n++)
arrayOfArrays[n] = new char[20];
That allocates an array of 10 arrays, each "child" array having 20 characters.
In C/C++, array access syntax is just a way of retrieving a value some distance away from a pointer.
char *p = "Hello";
char *pl = p + 2; // get pointer to middle 'l'
char l = *pl; // fetch
char o = p[4]; // use array syntax instead
void display(char ** array)
should work. Also I don't think that it is a reserved word in standard C/C++.
And also, why is array a reserved word?
It isn't. You are probably using Visual Studio where it's displayed as a keyword due to its use in C++/CLI as a native managed type. However, this is irrelevant for C++ and Visual Studio is misleading in that regard.
As to your problem: You can simply pass a pointer-to-pointers-to-char and then pass your nested array directly (provided you are working with a dynamically allocated array):
void display(char** array) …
That said, your function assumes a fixed, known array length and some other details. Better would be to use a nested std::vector, or std::string (for instance). Using such existing data types makes your life much easier.
void display(std::vector<std::string> const& array) {
for (size_t i = 0; i < array.length(); ++i)
cout << array[i] << endl;
}
To take advantage of this, your calling code needs to be changed as well to use these data structures instead of plain C arrays on chars.
The Earwicker's answer is missing an important fact. What he is proposing is an array of arrays. For the first this wastes memory for the array of pointers ("char **arrayOfArrays = new char *[10]" is the creation point of this). For the second the array of chars may then not be a continuous block of memory, which is often a problem.
The only workaround in C++ is to create a one dimensional array and calculate the indexes when you need them.
char *b = new char[width*height];
then you can refer to element x,y (x is along width, y along height) like this
char c=b[width*y+x];
This may be however a bit slower than the solution above (measured on GCC 3.4.5), so if you are not interested in continuous memory (for example you always access the elements with [][], never by adding integer to a pointer and dereferencing it), then you should use the array af arrays. However, if you are interested in having the continuous memory, e.g. to pass it as initializer to an std::string object or to send it as a whole through a network, you should use the second one.
The best is to use pointers, but Borland C++ admits passing arrays as parameters for functions. Look at this code (includes: iostream and conio):
////////////////////////////////////////////
void ReceivedArray(char x[5]){
for (int i=0; i<5; i++ )
cout << x[i];
}
void main(){
char *x = new char[5];
for (int i=0; i<5; i++ )
x[i]='o';
ReceivedArray(x);
getchar();
}
///////////////////////////////////////////////////////////////
For passing 2D arrays (oops! some lines in spanish, sorry!):
(includes: iostream, stdlb, stdio and math)
/////////////////////////////////////////////////
using namespace std;
void ver(int x[][20]){
for(int i=0; i<15; i++) {
for(int j=0; j<20; j++) {
cout<< x[i][j] <<" "; }
cout << "\n"; }
}
void cambiar0(int x[][20]){ int n[255];
for (int i=255; i>=0; i--)
n[255-i]=i;
for(int i=0; i<15; i++)
for(int j=0; j<20; j++)
for(int k=0; k<255; k++)
if(x[i][j]==n[k]) {
x[i][j]=k; break; }
}
int main(int argc, char* argv[]){
int x[15][20]; char a;
for(int i=0; i<15; i++)
for(int j=0; j<20; j++)
x[i][j]=rand()%255;
cout << "¿desea ver la matriz? s/n ";
cin >> a;
if(a=='s') ver(x);
cambiar0(x);
cout << "\n\n";
cout << "¿desea ver la matriz? s/n ";
cin >> a;
if(a=='s') ver(x);
system("PAUSE"); return 0;
}
///////////////////////////////////
Hope this is what you meant.
arr is a pointer to the multi-dimesional array you have and is actually a pointer to an int. Now since your function accepts a pointer to an int pointer, you need to get the address of arr using: &arr and pass that to the function so that you will have this code:
To coerce the array: Pass &arr to the function.
To reference the array inside the func: *maze[x][y]