Issue with variable as dimension to 2-D array in C++ - c++

Following code runs fine -
void func(int m[][2])
{
cout<<(m[0][0])<<endl;
}
int main()
{
// int x=2;
int m[2][2];
m[0][0] = m[0][1] = m[1][0] = m[1][1] = 5;
cout<<m[0][0]<<endl;
func(m);
}
But when I change main() as follows -
int main()
{
int x=2;
int m[x][x];
m[0][0] = m[0][1] = m[1][0] = m[1][1] = 5;
cout<<m[0][0]<<endl;
func(m);
}
I get the error message -
try.cpp:16:11: error: cannot convert ‘int (*)[(((long unsigned int)(((long int)x) + -0x00000000000000001)) + 1)]’ to ‘int (*)[2]’ for argument ‘1’ to ‘void func(int (*)[2])’
Also, the following runs fine -
int main()
{
int x=2;
int m[x][x];
m[0][0] = m[0][1] = m[1][0] = m[1][1] = 5;
cout<<m[0][0]<<endl;
//func(m);
}
Can anyone explain the issue here? Thanks.

Variable length arrays are not valid in C++. g++ allows this as an "extension".
int x=2;
int m[x][x]; //Illegal in C++
You should go for Dynamic Memory allocation if you want to dynamically allocate memory to an array.
int x=2;
int *m = new int[x];
It is better if you use STL :
int x = 10;
std::vector<int> m(n);
Or you can use const not a variable when creating it.
const int x=2; //it's a compile time constant
int m[x][x];

Related

passing in int* for int[][] C/C++

Suppose I have the following code
#include <stdio.h>
#include <stdlib.h>
int foo(int bar[3][3]){
return bar[1][1];
}
int main(){
int* bar = (int*) malloc(9 * sizeof(int));
for(int i = 0; i < 9; i++){
bar[i] = i;
}
int test = foo(bar);
printf("%d\n", test);
}
Compiling this with C gives a warning
warning: incompatible pointer types passing 'int *' to parameter of type 'int (*)[3]' [-Wincompatible-pointer-types]
int test = foo(bar);
But still outputs the expected result of 4 (Although I imagine the warning is a sign of UB)
Compiling with g++ gives an error
error: no matching function for call to 'foo'
int test = foo(bar);
note: candidate function not viable: no known conversion from 'int *' to 'int (*)[3]' for 1st argument
int foo(int bar[3][3]){
I cannot change the function signature of bar but would like to just pass in a simple pointer to the array. What is the simplest typecast/change of code that would make this compile with no UB with g++. This is for code that I am generating with a Python script while looking at the function signature of bar so the simpler the solution the better. (This is just an example)
Quick and dirty fix:
foo(reinterpret_cast<int(*)[3]>(bar)); // C++ only
foo((int(*)[3])bar); // C and C++
Replaces the implicit cast present in C language with an explicit one to let the C++ compiler know you are intending to circumvent the type-system.
Without dynamic memory allocation:
int main(void) {
int bar[3][3];
for (int i=0; i<9; ++i) {
bar[i / 3][i % 3] = i;
}
printf("%d\n", foo(bar));
}
With: (C)
int main(void) {
int (*bar)[3] = malloc(3 * sizeof(int[3]));
for (int i=0; i<9; ++i) {
bar[i / 3][i % 3] = i;
}
printf("%d\n", foo(bar));
}
What is the simplest typecast/change of code that would make this compile with no UB with g++
int main(){
int bar[3][3];
for(int i = 0; i < 9; i++){
bar[i / 3][i % 3] = i;
}
int test = foo(bar);
printf("%d\n", test);
}
Works in both C++ and C

c++/error :: exc_bad_access error code=1

Im getting a runtime error of exc_bad_access ( code = 1, address=0x0) on line
asize = **y[0] + **y[1];
in the summation function.
I know the problem is not a memory leak, so i don't quite know how to go about solving this problem.
void allocArr (int **&x, int ***&y, int **&q, int ****&z)
{
x = new int *[2];
y = new int **(&*x);
q = &*x;
z = new int ***(&q);
}
void summation(int ***&y, int arr[])
{
int asize = 0;
asize = **y[0] + **y[1];
**y[2] = *new int [asize];
*(arr + 2) = asize;
}
void putArr(int **&x, const int &size1,const int &size2)
{
x[0] = *new int* [size1];
x[1] = *new int* [size2];
}
int main()
{
int size1, size2;
int a = 1, b = 2;
int** x;
int*** y;
int** q;
int**** z;
int arr[2];
allocArr(x, y, q, z);
Input(x, arr, size1, size2, a, b);
summation(y, arr);
display(z);
}
Thank you for the help.
Three things.
1.)The function arguments for y are int *& . Did you overload int with a bracket operator somewhere else? As specified, the int pointer should not have a [].
2.) Bracket operators are higher in precedence than a dereference operator. (Almost always a good idea to enclose them within parenthesis). The way this is written, the bracket operator will be performed before the deref.
3.) It seems unusual that you should need so many dereference operators. Are they really necessary?

c++ error :: EXC_BAD_ACCESS for pointer arrays

I keep getting the error message, exc_bad_access code=1 for my line
asize = *(***(y) + **(y + 1));
in the summation function. I dont quite understand what to do with this error, but i know that it is not a memory leak.
I am trying to get the values stored in the y pointer array, add them, and store it in the variable asize.
void allocArr (int **&x, int ***&y, int **&q, int ****&z)
{
x = new int *[2];
y = new int **(&*x);
q = &*x;
z = new int ***(&q);
}
void putArr(int **&x, int &size1, int &size2)
{
*(x) = *new int* [size1];
*(x + 1) = *new int* [size2];
}
void Input (int **&x, int *&arr, int &size1,int &size2, int a, int b)
{
cout << "Please enter 2 non-negative integer values: "<< endl;
checkVal(size1, a);
checkVal(size2, b);
putArr(x, size1, size2);
arr[0] = size1;
arr[1] = size2;
cout << x[0];
}
void summation(int ***&y, int *&arr)
{
int asize = 0;
asize = *(***(y) + **(y + 1));
**y[2] = *new int [asize];
*(arr + 2) = asize;
}
int main()
{
int size1, size2;
int a = 1, b = 2;
int** x;
int*** y;
int** q;
int**** z;
int *arr = new int [2];
allocArr(x, y, q, z);
Input(x, arr, size1, size2, a, b);
summation(y, arr);
display(z);
}
Thank you for the help. Im really struggling here...
Not sure how you got started with the code. The code can be simplified quite a bit to help you, and readers of your code, understand what's going on.
Function allocArr
The lines
y = new int **(&*x);
q = &*x;
can be
y = new int **(x); // &*x == x
q = x;
Function putArr
You have the function declaration as:
void putArr(int **&x, int &size1, int &size2)
It can be changed to:
void putArr(int **x, int size1, int size2)
without changing how you are using the variables.
Your code in the function seems strange. Did you mean for x[0] and x[1] to point to an array of size1 and size2 ints, respectively? If you did, the code would be:
x[0] = new int[size1];
x[1] = new int[size2];
If you don't mean the above, it's hard to figure out what you are trying to do with your code.
Function Input
You have the function declaration as:
void Input (int **&x, int *&arr, int &size1,int &size2, int a, int b)
It can be changed to:
void Input (int **x, int *arr, int &size1,int &size2, int a, int b)
without changing how you are using the variables.
You are calling a function checkVal, but your posted code doesn't have that function. It's not clear what that function is doing. You have the line
cout << "Please enter 2 non-negative integer values: "<< endl;
just before the calls to checkVal. Presumably, checkVal reads the input and stores them in size1 in the first call and size2 in the second call. It's not clear how the second argument to checkVal is used.
And then, you have the line:
cout << x[0];
It's not clear what you wish to accomplish from printing an int* to cout. Perhaps it was part of your debugging code. The line doesn't change anything else in the program. It's just strange to see it there.
Function summation
You have the function declaration as:
void summation(int ***&y, int *&arr)
It can be changed to:
void summation(int ***y, int *arr)
without changing how you are using the variables.
In this function, you have the expression:
asize = *(***(y) + **(y + 1));
What do you get when you evaluate ***(y)?
***(y) = **(*y) = **(x) = *(*x) = *(x[0]) = uninitialized value from the line:
x[0] = new int[size1];
You will get unpredictable behavior when you use an uninitialized value.
The second term of the line, **(y + 1) is the worse culprit.
You allocated memory for y as:
y = new int **(&*x);
It's a pointer to a single object of type int**, not an array. y+1 is not a valid pointer. Dereferencing (y+1) leads to undefined behavior. In your case, you are seeing exc_bad_access, which makes sense now since you are accessing memory that is out of bounds.
Since I don't know what you are trying to compute in that expression, it's hard for me to suggest something useful. I hope you have enough to take it from here.

Pointer to a Matrix is throwing exception in c++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I work with dynamic multi-dimensional arrays in C?
Static Matrix Casting to a pointer
my this code is throwing exception at line
resMat[i][j] = matp[i][j];
// code begins here
#include <iostream>
#define MOD 1000000007
#define LL long long
using namespace std;
int mat[6][64][64],mat2[2][2], mat4[4][4], mat8[8][8], mat16[16][16], mat32[32][32], mat64[64][64];
int **point[6];
int resMat[64][64];
void fooMatrix(int **matp, int size)
{
int i,j;
// find canFollow of all matrixes
for(i=0;i<size;++i)
{
for(j=0;j<size;++j)
{
// throwing exception here
resMat[i][j] = matp[i][j];
}
}
}
int main()
{
point[0] = (int **)mat2;
point[1] = (int **)mat4;
point[2] = (int **)mat8;
point[3] = (int **)mat16;
point[4] = (int **)mat32;
point[5] = (int **)mat64;
LL a,b,res;
scanf("%lld %lld",&a,&b);
fooMatrix(point[a-1],1<<a);
return 0;
}
i want to process on different sized matrices of int in my function fooMatrix like say store it in resMat. Help me resolve this issue.
I am using DevC++ (g++ compiler) in windows.
Reading from the comments and links above i learnt this :
matrix represntation [][] and pointers representation ** is different. Compiler was giving me warning.
2d matrix is not array of pointers. so look at the code below
#include <stdio.h>
#define MOD 1000000007
#define LL long long
int mat[6][64][64],mat2[2][2], mat4[4][4], mat8[8][8], mat16[16][16], mat32[32][32], mat64[64][64];
// see this is array of single pointer
int *point[6];
int resMat[64][64];
void fooMatrix(int *matp, int size)
{
int i,j;
// find canFollow of all matrixes
for(i=0;i<size;++i)
{
for(j=0;j<size;++j)
{
// this is how we would access the matrix.
resMat[i][j] = matp[i*size+j];
}
}
}
int main()
{
point[0] = &mat2[0][0];
point[1] = &mat4[0][0];
point[2] = &mat8[0][0];
point[3] = &mat16[0][0];
point[4] = &mat32[0][0];
point[5] = &mat64[0][0];
LL a,b,res;
scanf("%lld %lld",&a,&b);
fooMatrix(point[a-1],1<<a);
return 0;
}
Instead of using matrices, you will have to use dynamically allocated arrays of pointers to arrays.
You can replace the declarations at the top of the file with the following:
int** newMat(int a, int b){
int** result = new int*[a];
for(int i=0; i<a; ++i)
result[i] = new int[b];
return result;
}
int** mat2 = newMat(2,2);
int** mat4 = newMat(4,4);
int** mat8 = newMat(8,8);
int** mat16 = newMat(16,16);
int** mat32 = newMat(32,32);
int** mat64 = newMat(64,64);
int*** point = new int**[6];
int** resMat= newMat(64,64);
And then change the assignments at the top of main with:
point[0] = mat2;
point[1] = mat4;
point[2] = mat8;
point[3] = mat16;
point[4] = mat32;
point[5] = mat64;

Compiler error: invalid conversion from 'int' to 'int*' [-fpermissive]|

I got a compiler error:
main.cpp|59|error: invalid conversion from 'int' to 'int*' [-fpermissive]|
The offending line is
int *pComienzo = vector, *pFinal = vector[nElementos-1];
Why there is an error? Can someone help me?
Below is my code:
#include <iostream>
#include <ctype.h>
using namespace std;
const unsigned short int MAX_VAL = 10;
int LongitudCadena(char*);
int BuscarCaracter(char *cadena, char caracter);
void Ordenar(int *vector, int nElementos, bool ascendente);
int main()
{
char *cadena = "asdasd";
cout << LongitudCadena(cadena) << endl;
cout << BuscarCaracter(cadena, 'a') << endl;
int iArray[] = {5,4,3,2,1};
Ordenar(iArray, 5, 1);
cout << iArray << endl;
return 0;
}
int LongitudCadena(char *cadena)
{
char *c = cadena;
for(int i = 0; i < MAX_VAL; i++)
{
if (c[i] == 0) break;
cadena++;
}
return cadena - c;
}
int BuscarCaracter(char * cadena, char caracter)
{
char *pCadena = cadena;
for (int i = 0; i < MAX_VAL; i++)
{
pCadena++;
if (toupper(cadena[i]) == toupper(caracter))
return pCadena- cadena;
}
return -1;
}
void Ordenar(int *vector, int nElementos, bool ascendente)
{
int *pComienzo = vector, *pFinal = vector[nElementos-1];
if (ascendente)
{
for (int i = 0; i < nElementos; i++)
{
for (; pComienzo < pFinal; pComienzo++, pFinal--)
{
if (*pComienzo > *pFinal)
{
*pComienzo += *pFinal;
*pFinal -= *pComienzo;
*pComienzo -= *pFinal;
}
}
}
}
}
I'm learning...
Your error is in this line:
int *pComienzo = vector, *pFinal = vector[nElementos-1];
The reason for this is that vector is an int*, but vector[nElementos - 1] is a regular int. Thus the declaration
int *pFinal = vector[nElementos - 1];
is trying to assign the integer value at the last index of vector to the pointer pFinal, hence the compiler error.
To fix this, you may want to do either
int *pFinal = &vector[nElementos - 1];
which makes pFinal point to the last element of vector, or
int *pFinal = vector + (nElementos - 1);
which accomplishes the same thing using pointer arithmetic.
That said, since you're working in C++, why not use the provided std::vector type and avoid working with pointers altogether?
Hope this helps!
vector is a pointer, but subscripting it as vector[nElementos-1] dereferences it to simply an int. What it looks like you want is instead
int *pComienzo = vector, *pFinal = &(vector[nElementos-1]);
An array access/subscript (i.e., a[i] where a is an array/pointer and i is an integer) is an expression with the type being the thing you have in the array.
Simply use the address-of operator & to store the address in the pointer:
int *pComienzo = vector, *pFinal = &vector[nElementos-1];
You forgot &. vector[nElementos-1] is the value, while you need an address for pFinal.
Either *pFinal = &(vector[nElementos-1]) or *pFinal = vector + nElementos-1.