This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do I use arrays in C++?
i have a problem.
i have to use auto darray(matrix).
const int size_m=10;
const int size_n=10;
void process(int *x)
{
//i can pass array, all is well, i work as with dynamic allocated array
for(int i=0;i<size_m;scanf("%d",&x[i]),i++);
}
void input_m(int **x)
/*
mistake is here,
a cause of my problem that i'm trying to work with matrix allocated in stack(auto matrix,local) as with dynamically allocated matrix.
i receive error like this : "cannot convert ‘int [100][100]’ to ‘int**’ in assignment" how should i pass it?
*/
{
for(int i=0;i<size_m;i++)
for(int j=0;j<size_n;j++)
scanf("%d",&x[i][j]);
}
int main()
{
int x[size_m];
input(x);
int matr_x[size_m][size_n];
input_m(matr_x);
return 0;
}
THANK YOU! it works.. it was so simple, as usual)
const int sizem=3;
const int sizen=3;
void _input(int x[sizem][sizen])
{
for(int i=0;i<sizem;i++)
for(int j=0;j<sizen;x[i][j]=1,j++);
}
int main()
{
int m=10,n=10;
int x[sizem][sizen]={{1,2,3},{5,7,4}};
_input(x);
for(int i=0;i<sizem;i++)
{ for(int j=0;j<sizen;printf(" %d",x[i][j]),j++);
puts("");
}
puts("");
return 0;
}
Your two-dimensional array is incompatible with the function you wrote for fundamental reasons of how memory works in C.
When you write int matrix[size_m][size_n] you are telling the compiler that you want a block of sizeof(int)*size_m*size_n bytes and you intend to store integers in it.
When you write int ** x you are telling the compiler that x is a pointer to a pointer to an integer. If you want to use x as a two-dimensional array, then x should point to not just one pointer, but the first pointer in an array of pointers, i.e. a contiguous region of memory that contains pointers for each row of your matrix. But you don't have any such array of pointers anywhere in the program you posted.
Since you know the dimensions of your matrix at compile time, you can fix this by changing the type of x be int x[size_m][size_n]. Better yet, make a typedef:
typedef int MyMatrix[size_m][size_n];
void input_m(MyMatrix x){ ... }
int main()
{
MyMatrix matr_x;
...
}
First of all, see the answer to this question. Your code should compile if you change void input_m(int **x) to void input_m(int x[size_m][size_n]) (assuming that both size_m and size_n are constants). Note that, as stated in the question that I linked to, "in general, to pass 2D arrays to functions you need to specify the array dimensions for all but the first dimension."
Related
This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
Closed 4 years ago.
In the program below the length of the array ar is correct in main but in temp it shows the length of the pointer to ar which on my computer is 2 (in units of sizeof(int)).
#include <stdio.h>
void temp(int ar[]) // this could also be declared as `int *ar`
{
printf("%d\n", (int) sizeof(ar)/sizeof(int));
}
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", (int) sizeof(ar)/sizeof(int));
temp(ar);
return 0;
}
I wanted to know how I should define the function so the length of the array is read correctly in the function.
There is no 'built-in' way to determine the length inside the function. However you pass arr, sizeof(arr) will always return the pointer size. So the best way is to pass the number of elements as a seperate argument. Alternatively you could have a special value like 0 or -1 that indicates the end (like it is \0 in strings, which are just char []).
But then of course the 'logical' array size was sizeof(arr)/sizeof(int) - 1
Don't use a function, use a macro for this:
//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", arrayLength(ar));
return 0;
}
You still cannot use this macro inside a function like your temp where the array is passed as a parameter for the reasons others have mentioned.
Alternative if you want to pass one data type around is to define a type that has both an array and capacity:
typedef struct
{
int *values;
int capacity;
} intArray;
void temp(intArray array)
{
printf("%d\n", array.capacity);
}
int main(void)
{
int ar[]= {1, 2, 3};
intArray arr;
arr.values = ar;
arr.capacity = arrayLength(ar);
temp(arr);
return 0;
}
This takes longer to set up, but is useful if you find your self passing it around many many functions.
As others have said the obvious solution is to pass the length of array as parameter, also you can store this value at the begin of array
#include <stdio.h>
void temp(int *ar)
{
printf("%d\n", ar[-1]);
}
int main(void)
{
int ar[]= {0, 1, 2, 3};
ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
printf("%d\n", ar[0]);
temp(ar + 1);
return 0;
}
When you write size(ar) then you're passing a pointer and not an array.
The size of a pointer and an int is 4 or 8 - depending on ABI (Or, as #H2CO3 mentioned - something completely different), so you're getting sizeof(int *)/sizeof int (4/4=1 for 32-bit machines and 8/4=2 for 64-bit machines), which is 1 or 2 (Or.. something different).
Remember, in C when pass an array as an argument to a function, you're passing a pointer to an array.If you want to pass the size of the array, you should pass it as a separated argument.
I don't think you could do this using a function. It will always return length of the pointer rather than the length of the whole array.
You need to wrap the array up into a struct:
#include<stdio.h>
struct foo {int arr[5];};
struct bar {double arr[10];};
void temp(struct foo f, struct bar g)
{
printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}
void main(void)
{
struct foo tmp1 = {{1,2,3,4,5}};
struct bar tmp2;
temp(tmp1,tmp2);
return;
}
Inside the function ar is a pointer so the sizeof operator will return the length of a pointer. The only way to compute it is to make ar global and or change its name. The easiest way to determine the length is size(array_name)/(size_of(int). The other thing you can do is pass this computation into the function.
This question already has answers here:
Passing a 2D array to a C++ function
(18 answers)
Closed 7 years ago.
I have in class County.h constructor:
struct Country {
Country(double**, int);
};
and in main I have graph[Size][Size] and I want to call the constructor for County.
int main() {
double graph[Size][Size];
Country c(graph, 0);
}
But its giving me error no matching function for call to ‘County::County(double [22][22], int)’
What I can do in order to solve this problem?
double [Size][Size] and double** are not at all the same type. That is what your compiler doesn't like.
Change your constructor prototype or the way you declare your array. But you cannot directly cast an array of array to a pointer of pointer.
struct Country {
Country(double[Size][Size], int);
};
OR:
int main() {
double** graph = new (double*)[Size];
for (int i = 0; i < Size; ++i) {
graph[i] = new double[Size];
}
Country c(graph, 0);
// Don't forget to delete your graph then.
}
Note that the first one requires that you would know the size before your code start its execution (storing Size in a macro for instance), but the second one is longer to code, and you will have to manipulate more RAM memory, that can lead to mistakes if you are not careful.
An alternative is to declare your constructor as a template and pass the array by (const) reference,
struct Country {
template<size_t N>
Country(double /*const*/ (&arr)[N][N], int);
};
In this way, the template will deduce the size of the array directly. Of course, the downside is that the above won't work with double pointers. The upside is that the compiler will strongly check the type and your program won't even compile if the array is not made of doubles (no conversions are being performed at type deduction) or if it is not square.
There are tons of similar questions, but still I could not find any answer relevant for the feature of variable length arrays in C99/C11.
How to pass multidimensional variable length array to a function in C99/C11?
For example:
void foo(int n, int arr[][]) // <-- error here, how to fix?
{
}
void bar(int n)
{
int arr[n][n];
foo(n, arr);
}
Compiler (g++-4.7 -std=gnu++11) says:
error: declaration of ‘arr’ as multidimensional array must have bounds for all dimensions except the first
If I change it to int *arr[], compiler still complains:
error: cannot convert ‘int (*)[(((sizetype)(((ssizetype)n) + -1)) + 1)]’ to ‘int**’ for argument ‘2’ to ‘void foo(int, int**)’
Next question, how to pass it by value and how to pass it by reference? Apparently, usually you don't want the entire array to be copied when you pass it to a function.
With constant length arrays it's simple, since, as the "constant" implies, you should know the length when you declare the function:
void foo2(int n, int arr[][10]) // <-- ok
{
}
void bar2()
{
int arr[10][10];
foo2(10, arr);
}
I know, passing arrays to functions like this is not a best practice, and I don't like it at all. It is probably better to do with flat pointers, or objects (like std:vector) or somehow else. But still, I'm a bit curios what is the answer here from a theoretical standpoint.
Passing arrays to functions is a bit funny in C and C++. There are no rvalues of array types, so you're actually passing a pointer.
To address a 2D array (a real one, not array of arrays), you'll need to pass 2 chunks of data:
the pointer to where it starts
how wide one row is
And these are two separate values, be it C or C++ or with VLA or without or whatnot.
Some ways to write that:
Simplest, works everywhere but needs more manual work
void foo(int width, int* arr) {
arr[x + y*width] = 5;
}
VLA, standard C99
void foo(int width, int arr[][width]) {
arr[x][y] = 5;
}
VLA w/ reversed arguments, forward parameter declaration (GNU C extension)
void foo(int width; int arr[][width], int width) {
arr[x][y]=5;
}
C++ w/ VLA (GNU C++ extension, terribly ugly)
void foo(int width, int* ptr) {
typedef int arrtype[][width];
arrtype& arr = *reinterpret_cast<arrtype*>(ptr);
arr[x][y]=5;
}
Big remark:
The [x][y] notation with a 2D array works because the array's type contains the width. No VLA = array types must be fixed at compile-time.
Hence: If you can't use VLA, then...
there's no way to handle it in C,
there's no way to handle it without a proxy class w/ overloaded operator overloading in C++.
If you can use VLA (C99 or GNU C++ extensions), then...
you're in the green in C,
you still need a mess in C++, use classes instead.
For C++, boost::multi_array is a solid choice.
A workaround
For 2D arrays, you can make two separate allocations:
a 1D array of pointers to T (A)
a 2D array of T (B)
Then set the pointers in (A) to point into respective rows of (B).
With this setup, you can just pass (A) around as a simple T** and it will behave well with [x][y] indexing.
This solution is nice for 2D, but needs more and more boilerplate for higher dimensions. It's also slower than the VLA solution because of the extra layer of indirection.
You may also run into a similar solution with a separate allocation for every B's row. In C this looks like a malloc-in-a-loop, and is analogous of C++'s vector-of-vectors. However this takes away the benefit of having the whole array in one block.
There is no clear cut way for doing this but you can use a workaround to treat a 2 dimensional array as a one dimensional array and then reconvert it to a two dimensional array inside the function.
void foo2(int n, int *arr)
{
int *ptr; // use this as a marker to go to next block
int i;
int j;
for(i = 0; i < n; i++)
{
ptr = arr + i*n; // this is the starting for arr[i] ...
for (j = 0; j < n ;j++)
{
printf(" %d ", ptr[j]); // This is same as arr[i][j]
}
}
}
void bar2()
{
int arr[10][10];
foo2(10, (int *)arr);
}
This program must have a function that can accept 2 arrays and return their product in a third array. All of the arrays must be 2d, and a separate function must complete the multiplication of the elements memberwise. When I run this in visual studio I get the error:
Unhandled exception at 0x003f15ec in program4.exe: 0xC0000005:
Access violation reading location 0x00000000.
This could be due to my lack of knowledge about C++, but I think I may have made a syntax mistake or something.
Here is the program:
#include<iostream>
using namespace std;
void ProductArrays(int[3][4], int[3][4], int** array3[3][4]);
void main()
{
int array1[3][4] = { {1,3,5,7}, {9,11,13,15}, {17,19,21,23} };
int array2[3][4] = { {2,4,6,8}, {10,12,14,16}, {18,20,22,24} };
int** array3[3][4] = {0,0,0,0,0,0,0,0,0,0,0,0};
ProductArrays(array1, array2, array3);
system("pause");
return;
}
void ProductArrays(int array1[3][4], int array2[3][4], int** array3[3][4])
{
int i,j;
for (i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
**array3[i][j] = array1[i][j] * array2[i][j];
}
}
return;
}
I think what you mean for array3 to be a reference to a 2d array of pointers, but it's actually a 2d array of int**. So when you do the multiplication, this part:
**array3[i][j]
Is trying to dereference what's in array3[i][j], which is 0, hence the AccessViolation. I think you probably mean the signature to be:
void ProductArrays(int array1[3][4], int array2[3][4], int (&array3)[3][4])
And declare array3 to be of the same type as array1 and array2.
(1)
The declaration for array3 is wrong as you required.
int** array3[3][4] = {0,0,0,0,0,0,0,0,0,0,0,0};
You need this If I correctly understand you question:
int array3[3][4] = {0,0,0,0,0,0,0,0,0,0,0,0};
(3)
You are getting error because you were creating 2D array of pointers those are pointing to NULL (0) and you are assigning to 0 location.
**array3[i][j] = array1[i][j] * array2[i][j];
^ assign to `0` location
(2)
Declare you function like:
void ProductArrays(int array1[3][4], int array2[3][4], int (*array3)[4])
{ // ^ notice
int i,j;
for (i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
array3[i][j] = array1[i][j] * array2[i][j];
// ^ remove **
}
}
return;
}
call it from main like:
ProductArrays(array1, array2, array3);
Additional point, my answer is pass by address, and #Barry's answer is pass by reference. In C++ Both are allowed. (in C only pass by address is possible)
Pass by reference having power of pointers but simple to use like value variables So #Barry's answer is better. consider my answer for understanding points of view.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I use arrays in C++?
How do I pass 2-D array to function in c++ via pointer.
I get following error when I try the code below.
error: cannot convert 'int (*)[10][10]' to 'int **' for argument '1' to 'void fn(int **)'
void fn(int **a)
{
cout<<a[0][0]<<" "<<a[0][1];
}
int main()
{
int A[10][10];
A[0][0]=1;
A[0][1]=2;
fn(&A); //????
}
A 2d array, created the way you did, is contigous in memory. The compiler needs to know the size of each segment, to be able to move the pointer to the next one in your function. Writing fn(int (*a)[3]) or fn(int a[][3]) is equivalent. But let's take an example
char a[3][3];
a[0][0] = 01;
a[0][1] = 02;
a[0][2] = 03;
a[1][0] = 04;
a[1][1] = 05;
a[1][2] = 06;
a[2][0] = 07;
a[2][1] = 08;
a[2][2] = 09;
will become
|01|02|03|04|05|06|07|08|09|
in memory.
So if you pass a to a function, it needs to know that it has to increase the a ptr by 3 * sizeof(a) to access a[1][0].
In short : the prototype of the function needs to be void fn(int a[][10]) or void fn(int (*a)[10])
According to the link from #R. Martinho Fernandes , the following is valid C++:
int array_of_arrays[6][7];
int (*pointer_to_array)[7] = array_of_arrays;
So the following should also be valid:
void fn (int (*a)[10])
{
cout<<a[0][0]<<" "<<a[0][1];
}
And I believe the following is also valid:
void fn (int a[][10])
{
cout<<a[0][0]<<" "<<a[0][1];
}
You need to declare fn() as
void fn(int (&a)[10][10])
Arrays in C++ can be treated as pointers to the location of the first element of an array. A two dimensional array can be thought of as an array of pointers, and each of the pointers points to another array. While this isn't strictly speaking how arrays are implemented, C supports implicit conversion between arrays and pointers to the first element, and you can think of them as the same. Array[index] is just syntactical sugar for *(Array + index*sizeof(whatever's in the array)). So for your function to work, you can just do:
void fn(int (*a)[10]) {
cout<<a[0][0]<<" "<<a[0][1];
}
int main() {
int A[10][10];
A[0][0]=1;
A[0][1]=2;
fn(A);
}
No need to get the address of the array first, because it's already a pointer. However, because you're using C++, you really should consider using standard containers:
void fn(vector< vector<int> > const&a) {
cout<<a[0][0]<<" "<<a[0][1];
}
int main() {
vector< vector<int> > A( 10, vector<int>(10) );
A[0][0]=1;
A[0][1]=2;
fn(A);
}
C++ needs to know the array size (of one dimension) to perform 2d indexing.
try:
void fn(int a[][10]) {
cout<<a[0][0]<<" "<<a[0][1];
}