First of all: yes, I know this is a common topic and I've tried several proposed solutions. Nothing worked for me (at least nothing with "nice" code), I finally tried the way described here (2nd variant in jxh's solution):
2D array passing to a function
#include<stdio.h>
typedef double real32;
void Multiply_Matrix_Vector38(int n, int m, real32 A[n][m], real32 B[m], real32 Result[n]);
int main()
{
real32 A[3][8];
real32 B[8];
real32 Result[3][3];
int i;
for(i = 0; i < 8; i++) {
A[0][i] = i;
A[1][i] = i+1;
A[2][i] = i+2;
B[i] = i;
B[i] = i;
B[i] = i;
}
Multiply_Matrix_Vector(3, 8, A[3][8], B[8], Result[3]);
return 0;
}
void Multiply_Matrix_Vector(int n, int m, real32 A[n][m], real32 B[m], real32 Result[n])
{
uint8 i, j;
real32 sum;
sum = 0;
for(i = 0; i < n; i++ {
for(j = 0; j < m; j++) {
sum = sum + A[i][j] * B[j];
printf("A %f\n", A[i][j]);
}
Result[i] = sum;
sum = 0;
}
}
I still get incompatible type errors - how can this be fixed?
As arrays decays to pointers when being passed to a function, what's really passed is real32 (*)[8] and real32 *.
You can modify the function appropriately:
void Multiply_Matrix_Vector38(int n, int m, real32 (*A)[m], real32 *B, real32 *Result);
You also calling the function with the wrong arguments. You're calling it with a single value in the arrays, and not the arrays themselves. And remembering that array indexes goes from zero to size minus one, you're also out of bounds.
Instead do just
Multiply_Matrix_Vector(3, 8, A, B, Result);
Oh, and do you really want Result to be an array of arrays too?
Your are not passing the arrays when you do Multiply_Matrix_Vector(3, 8, A[3][8], B[8], Result[3]);
Rather, you are passing the element of A at (3,8), the 9th element of B.
Your call should be the following : Multiply_Matrix_Vector(3, 8, A, B, Result[0]);
The error should have helped you with that : your are passing doubles instead of arrays of doubles.
Result is n array of 3 arrays of size 3, thus Result[0], Result[1], and Result[2] have the correct types. Result[3] is out of bounds however.
Finally your function prototype should be void Multiply_Matrix_Vector(...) not void Multiply_Matrix_Vector38(...)
You missed a couple of things, like the ) in.
for(j = 0; j < m; j++)
Also you should have called
Multiply_Matrix_Vector(3, 8, A, B, Result[3])
Instead of.
Multiply_Matrix_Vector(3, 8, A[3][8], B[8], Result[3])
Because your arguments A[3][8] and B[8] are real32 variables (you are accesing to an element of the matrix and an element of the vector), instead of that you have to use A and B.
And finally, you have to declare.
void Multiply_Matrix_Vector(int n, int m, real32 A[n][m], real32 B[m], real32 Result[n]);
Above the main function to use it there.
Note: Result should be an array, because if multiply A (3x8) with B (8x1), the result should be an array with dimensions 3x1.
Related
This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 13 days ago.
I wrote this program that is supposed to sort NxN array. It gets compiled but doesn't work because the pointer type is incompatible.
I just need help with the pointers as argument. I get incompatible pointer type warning for both functions swap and dblArraySort. Any idea why is that ?
thanks in advance !
#include <stdio.h>
#include <stdlib.h>
void
swap(int **a, int **b)
{
int temp;
temp = **a;
**a = **b;
**b = temp;
}
void
dblArraySort(int **dblArray, int arrLen)
{
int chkIndex;
int i, j, k;
for (i = 0; i < arrLen; i++) {
if ((i + 1) % 2 == 0) {
for (j = 0; j < arrLen; j++) {
chkIndex = dblArray[i][j];
for (k = 1; k + j < arrLen; k++)
if (chkIndex < dblArray[i][k + j])
swap(&dblArray[i][j], &dblArray[i][k + j]);
else
continue;
}
} else {
for (j = 0; j < arrLen; j++) {
chkIndex = dblArray[i][j];
for (k = 1; k + j < arrLen; k++)
if (chkIndex >= dblArray[i][k + j])
swap(&dblArray[i][j], &dblArray[i][k + j]);
else
continue;
}
}
}
}
int
main()
{
unsigned int arrayLength;
printf("Provide array size: \n");
scanf("%d", &arrayLength);
int doubleArray[arrayLength][arrayLength];
for (int i = 0; i < arrayLength; i++) {
for (int j = 0; j < arrayLength; j++) {
scanf("%d", &doubleArray[i][j]);
}
}
dblArraySort(doubleArray, arrayLength);
for (int i = 0; i < arrayLength; i++) {
for (int j = 0; j < arrayLength; j++) {
printf("%d ", doubleArray[i][j]);
}
printf("\n");
}
return 0;
}
I tried the code mentioned above
Arrays in C can be confusing. The thing you need to worry about is element type.
The element type of int ** dblArray is int *. In other words, dblArray is an array of int *s.
However, the element type of int doubleArray[arrayLength][arrayLength] is int row_type[arrayLength]. That is not an int *, that is an array, which is a totally different thing.
Moreover, when you use an array⟶pointer conversion, as happens when you say:
dblArraySort(doubleArray, arrayLength); // doubleArray is converted to a pointer
You get a pointer to the array, which in this case is a pointer to the innermost element type, an int — which is also not an int *.
tl;dr: You are trying to pass an array of array of int to a function taking an array of pointer to int. That won’t work.
I would like to comment on your variable naming as well. When you say “double” or “dbl”, as in doubleArray and dblArray the very first thing people will think is that you are handling a linear array of type double, which is also not what the array is.
You have there a two-dimensional array. Not a “double” array. Common naming for such thing would be array2D or matrix.
To make it work you need either C11, which allows you to pass a VLA as:
void sort_array2D( size_t rows, size_t columns, int array[rows][columns] )
{
...
int value = array[i][j];
...
}
int main(void)
{
int array2D[Array_Length][Array_Length];
...
sort_array2D( Array_Length, Array_Length, array2D );
Or you need to simply assume you must compute the index manually. A little function will help:
size_t index2D( size_t rows, size_t columns, size_t r, size_t c )
{
(void)rows; // (quiet the compiler about not using this argument)
return r * columns + c;
}
Then you can write your function as:
void sort_array2D( int * array, size_t rows, size_t columns )
{
...
int value = array[index2D( rows, columns, i, j )];
...
}
int main(void)
{
int array2D[Array_Length][Array_Length];
...
sort_array2D( (int *)array2D, Array_Length, Array_Length );
I haven’t bothered to analyze your sort function. It doesn’t look right to me, but honestly, I’ve barely glanced at it. Calling a value from the array chkIndex looks fishy, since the values of the array are not indices per se, at least not in the context of sorting them.
Remember, when messing with arrays in C you need to keep strict care to not mix up the type of the elements. (Or the types of things in general, whether syntactic or conceptual.)
This question already has answers here:
How to pass a 2D array by pointer in C?
(5 answers)
Closed 4 months ago.
#include <stdio.h>
void triU(double **U, double *b, int n)
{
n--;
b[n] /= U[n][n];
for(int i = n - 1; i >= 0; i--)
{
double aux_sum = 0;
for(int j = i + 1; j <= n; j++)
aux_sum += (U[i][j] * b[j]);
b[i] = (b[i] - aux_sum) / U[i][i];
}
}
int main()
{
int n = 3;
double U[][n] = {{5, -5, 10}, {0, 2, 4}, {0, 0, -1}};
double b[] = {25, 16, -2};
triU(U, b, n);
for(int i = 0; i < n; i++)
printf("%le \n", b[i]);
return 0;
}
This is the code for what I am trying to do. I am supposed to make a method with the parameters written in that way to pass the two matrices.
However I keep getting the following error.
triU.c: In function ‘int main()’:
triU.c:21:10: error: cannot convert ‘double (*)[n]’ to ‘double**’
21 | triU(U, b, n);
| ^
| |
| double (*)[n]
triU.c:3:20: note: initializing argument 1 of ‘void triU(double**, double*, int)’
3 | void triU(double **U, double *b, int n)
| ~~~~~~~~~^
I would appreciate any help on how I am supposed to pass arrays by pointers in C.
Thank you very much.
In this call of the function triU:
triU(U, b, n);
the two-dimensional array U is implicitly converted to pointer to its first element of the type double ( * )[3]. But the corresponding function parameter has the type double ** and there is no implicit conversion between the pointer types. So the compiler issues a message.
If your compiler supports variable length arrays (and your compiler support VLAs) then declare the function like:
void triU( size_t n, double ( *U )[n], double *b );
or:
void triU( size_t n, double U[][n], double *b );
and call it like:
triU( n, U, b );
Otherwise declare the function like:
void triU( double ( *U )[3], double *b, size_t n );
or:
void triU( double U[][3], double *b, size_t n );
and call it like:
triU( U, b, n );
Pay attention to that this for loop:
for(int j = i + 1; j <= n; j++)
aux_sum += (U[i][j] * b[j]);
can invoke undefined behavior when j is equal to n because the valid range of indices is [0, n).
Also bear in mind that the length modifier in the format string in this call:
printf("%le \n", b[i]);
is redundant and has no effect. You may write:
printf("%e \n", b[i]);
Consider following declaration:
int a[M][N]; // M and N are known compile-time
Would it be legal to treat it like as it was declared as:
int a[N][M];
or even:
int a[A][B]; // where A * B = M * N
in C without breaking its rules (badly)?
I found that it can be acomplished without any cast:
#include <stdio.h>
void print_array(int a[][2], int n);
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
//int (*p1)[2] = a; // compile error
int (*ptr_temp)[] = a; // pointer to array of incomplete type
int (*p2)[2] = ptr_temp; // compiles without any warning
print_array(p2, 3);
}
void print_array(int a[][2], int n)
{
for (int i = 0; i < n; i++)
for (int j = 0; j < 2; j++)
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
Notice that we cannot assign a to p1 pointer directly. However compiler does not complain when p2 is assigned with ptr_temp even if it seems to be potentially dangerous (it does not require any cast for that). Is it really sanitized? If so, then why it disallows the first assignmment?
The behavior you see is because of the way multidimensional arrays are handled in C.
Have a look at this question Pointer address in a C multidimensional array
How do I feed an array of pointers as an argument to a function?
In the code below, if I want my function f to take an array of pointers int *x[], how should I declare x in main() and feed it as argument to f?
void f(int *x[]){
int data[5] = {1,2,3,4,5};
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
int main(){
int *(x[]), k, l=5;
f(x); // this does not work
for(k=0; k<l; k++){
printf("x[%d] = %d\n", k, *x[k]);
}
}
return 0;
}
Writing f(x) does not work, and neither does f(x[]) or f(x[5]).
In fact, the declaration int *(x[]) is already not recognized by my compiler, while I thought that one could declare an array of pointers without specifying the length of the array.
In main, change
int *(x[])
to
int *x[SIZE]; // SIZE is array size
Note that, you can't declare a zero size array in C except when it is a last member of a structure.
After all, your code will invoke undefined behavior because the variable data is an automatic local variable and will not exist after function returns.
You may want this:
void f(int *x[]){
int *data = malloc(5*sizeof(int);
int temp[5] = {1,2,3,4,5};
memcpy(data, temp, 5*sizeof(int));
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
First of all your code has no sense because you are trying to fill an array of pointers that will point to local variables. That is after exiti8ng the function all pointers will be invalid because original objects will be already destroyed.
The code could have a sense if the array in the function would have static storage duration
void f(int *x[]){
static int data[5] = {1,2,3,4,5};
int k;
for(k=0; k<5; k++){
x[k] = &(data[k]);
}
}
In main array x should be defined at least as
int * x[5];
int main(){
int * x[5], k;
f(x);
for ( k=0; k < 5; k++ ){
printf("x[%d] = %d\n", k, *x[k]);
}
}
return 0;
}
An alternate way to declare an array of pointer as a parameter is to use a pointer of pointer
void f(int **x, int size){
//code
}
However, you'll have to pass the size as a second argument if you want to avoid an overflow.
To call the code you'll just have to do something like this :
int *a[] = { NULL, NULL, NULL};
f(a, 3);
I am using a recursive function (from one of the posts here) to enumerate all combinations of selecting k items out of n. I have modified this function to save and return the enumerated combinations in a 2-dimensional array (which is passed to the function as arrPtr). I call this recursive function in a for loop (from main) for different values of k (k from 1 to n-1) to generate all the combinations for any value of n and k. Now, with 'count', being defined as static integer, the function generates all the combinations for k=1 and then goes to k=2, but then stops at one point. The reason is that I'm using the variable 'count' as an index for rows in arrPtr. Since it is a static variable, it does not reset to 0 when the function is called for the other rounds (k=2,3,4 etc.). So it results in access violation for arrPtr after a certain point. When I remove 'static' for 'count', it generates all the combinations for different values of k, but only the last combination in each round is saved in arrPtr (again due to removing 'static'). How can I save each generated combination in a row in arrPtr so I can get (and return) all of the combinations saved in one place pointed to by arrPtr at the end?
I tried to pass the index for rows in arrPtr to the function using pass by reference (passing the address of the variable) but that gets into trouble when the recursive function calls itself.
I searched a lot and found similar topics here (e.g., returning arrays from recursive functions), but they are mostly for other programming languages (I only use C; not even C++). I have spent many many hours on solving this and really need help now. Thank you in advance.
int** nCk(int n,int loopno,int ini,int *a,int **arrPtr, int k)
{
static int count=0;
int total; // equal to the total number of combinations of nCk
int i,j;
total = factorial(n)/(factorial(n-k)*factorial(k));
loopno--;
if(loopno<0)
{
a[k-1]=ini;
for(j=0;j<k;j++)
{
printf("%d,",a[j]);
arrPtr[count][j]=a[j];
}
printf("count =%d\n",count);
count++;
return 0;
}
for(i=ini;i<=n-loopno-1;i++)
{
a[k-1-loopno]=i+1;
nCk(n,loopno,i+1,a,arrPtr,k);
}
if(ini==0)
return arrPtr; // arrPtr is in fact an array of pointers, where each pointer points to an array of size k (one of the combinations of selecting k out of n elements
else
return 0;
}
what i understand is
you want to calculate the combination for any value of n and k in nCk,
define a factorial() function outside and
define a combi() function ... which calculates Combination value of n and k variables
both function before defining the main() function... that way you can avoid declaration and then defining (i mean avoid extra lines of code).
here is the code for combi() function
function combi(int n , int k){
int nFact, kFact, n_kFact, p;
int comb;
nFact=factorial(n);
kFact=factorial(k);
p=n-k;
n_kFact=factorial(p);
comb= nFact / ((n_kFact) * kFact);
return comb;
}
you can call this function in your main function .... use for loop to store the combination value for relative n and k .... thus you will get what you need .... also pass pointer or
&array[0][0]
i.e. starting address for the array... so that you can access that array anywhere in the program.
hope this may help you. thanks
GCC 4.7.3: gcc -Wall -Wextra -std=c99 enum-nck.c
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// Textbook recursive definition of, n-choose-k.
int nCk(int n, int k) {
assert(0 < k && k <= n);
if (k == n) { return 1; }
if (k == 1) { return n; }
return nCk(n - 1, k) + nCk(n - 1, k - 1);
}
// But you asked for a procedure to enumerate all the combinations.
void aux_enum_nCk(int n, int k, int* all, int* j, int a[], int i) {
a[i] = n;
if (i == k - 1) {
memcpy(&all[*j], &a[0], k * sizeof(int));
*j += k;
return;
}
for (int c = n - 1; c > 0; --c) {
aux_enum_nCk(c, k, all, j, a, i + 1);
}
}
void enum_nCk(int n, int k, int* arr) {
assert(0 < k && k <= n);
int j = 0;
int a[k];
for (int i = 0; i < k; ++i) { a[i] = 0; }
for (int c = n; c >= n - k - 1; --c) {
aux_enum_nCk(c, k, arr, &j, a, 0);
}
}
int main(int argc, char* argv[]) {
int n = 7;
int k = 3;
int x = nCk(n, k);
printf("%d choose %d = %d\n", n, k, x);
int arr[x][k];
enum_nCk(n, k, &arr[0][0]);
for (int i = 0; i < x; ++i) {
for (int j = 0; j < k; ++j) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}