Reputation: 533
I am using Code:Block.
Compiled the following code(no errors) and while running got segmentation fault.
void print(int size, int **a)
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";/**Segmentation fault here**/
}
cout<<endl;
}
}
int main()
{
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int size = sizeof(a)/sizeof(a[0]);
print(size,(int **)a);
return 0;
}
I tried using different methods of passing the array:
void print(int size, int a[][4])
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int size = sizeof(a)/sizeof(a[0]);
print(size,a);
return 0;
}
I got no error, code ran successfully.
For the first code instead of using a[i][j]
, I tried with *(*(a+i)+j)
, got segmentation fault.
Then I debugged the first code at the point of segmentation fault and absorbed the following:
> p a
$1 = (int **) 0x22fd30
> p *a
$2 = (int *) 0x200000001
> p **a
Cannot access memory at address 0x200000001
I believe that a
hold the first address of the 2d array. but for p **a there is a different address shown in the error message.
Then I ran the first code in http://ideone.com/ and encountered run time error. Where am I making mistake? and why the debugger showing different address?.
Upvotes: 2
Views: 2128
Reputation: 307
The following works for me:
Allocation and assignment:
int** foo( int N, int M)
{
int** arr;
arr = (int **)malloc(sizeof(int *)*N);
for(int i=0; i < N; i++) {
arr[i] = (int *)malloc(sizeof(int)*M);
}
int x=0;
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
arr[i][j]=x;
x++;
}
}
return arr;
}
Now you can use it like this:
void print(int size, int a[][4])
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
int N=2;
int M=3;
int** foo = bar(N,M);
print(arr,N,M);
}
Upvotes: 1
Reputation: 1430
In your first example
void print(int size, int **a)
expects second argument of type pointer to pointer to int. But here
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
print(size,(int **)a);
you pass a variable of type array of 4 arrays of 4 ints. When you pass an array to function, array decays to pointer to its first element. So actually function print
gets argument of type int *[4]
- pointer to array of 4 ints which is not what print
expects. That's an error. You hide this error from compiler telling him that a
has type int **
. It doesn't. Hence the segmentation fault.
In your second example
void print(int size, int a[][4])
expects an argument of type array of arrays of 4 ints. It decays to int *[4]
which is exactly the type of a
when it decays while passed to print
function. No error here.
Upvotes: 3
Reputation: 1017
Problem you are facing is because of Data type of both is different. int arr[][] is different from int ** arr. Lets see from 1-d array when you declare int arr[], arr it is same as int *arr. When you try to access it arr[i] internally what compiler does *(arr+i). But when you declare int arr[][size] data type of arr is int (*arr)[size] which is different from int **arr. That's why you get error. see this Link
Upvotes: 1
Reputation: 552
If you index an int**, in your case a[0] for example, the resulting type is int*. If you index that again, as in a[0][0], it will interpret the first element (being the integer 1) (or first two elements on 64-bit) as a pointer to int (int*) and attempt to dereference it, which is obviously incorrect and will usually lead to a segmentation fault.
Your C-style cast (int**) is translated to a reinterpret_cast. Which is why I don't like C-style casts as it's not always obvious what they do.
In short: with your cast to (int**) you're telling the compiler that it's an array of pointers to int, which it isn't: it's an array of int[4]'s.
Edit: my comment about 64-bit only holds for platforms where sizeof(int) is always 4. I believe on linux sizeof(int) == sizeof(int*).
Upvotes: 2