Matrix power and pointers - c

I am trying to compute the power of the matrix A using multiplications.
I am having problems with the ArrayPower function. It does not function as i think it should.The MultiArray function however seems to work fine. Can anyone help me ?
#include <stdio.h>
int** MultiArray(int a[2][2],int b[2][2]);
int** ArrayPower(int a[2][2],int e);
int main(void)
{
int fa[2][2];
fa[0][0]=0;
fa[0][1]=1;
fa[1][0]=1;
fa[1][1]=1;
int **multifa=malloc(sizeof(int)*2);
for (int i=0;i<2;i++) {
multifa[i]=malloc(sizeof(int)*2);
}
multifa=ArrayPower(fa,2);
printf("%d %d\n",multifa[0][0],multifa[0][1]);
printf("%d %d\n",multifa[1][0],multifa[1][1]);
return 0;
}
int** MultiArray(int a[2][2], int b[2][2]) {
//multi a *b
//memory allocation
int i,rows=2,cols=2;
int **c=malloc(rows*sizeof(int));
for (i=0;i<rows;i++) {
c[i]=malloc(cols*sizeof(int));
}
c[0][0]=a[0][0]*b[0][0]+a[0][1]*b[1][0];
c[0][1]=a[0][0]*b[0][1]+a[0][1]*b[1][1];
c[1][0]=a[1][0]*b[0][0]+a[1][1]*b[1][0];
c[1][1]=a[1][0]*b[0][1]+a[1][1]*b[1][1];
return c;
}
int** ArrayPower(int a[2][2],int e) {
//memory allocation
int i,rows=2,cols=2;
int **c=malloc(rows*sizeof(int));
for (i=0;i<rows;i++) {
c[i]=malloc(cols*sizeof(int));
}
c[0][0]=a[0][0];
c[0][1]=a[0][1];
c[1][0]=a[1][0];
c[1][1]=a[1][1];
for (i=1;i<e;i++) {
c=MultiArray(a,c);
}
return c;
}

MultiArray is declared as taking a second parameter of type int [2][2], but it is called with an argument of c, which as type int **. These are not compatible types.
In a parameter, the type int [2][2] is automatically converted to a pointer to an array of two int, the type int (*)[2]. This is a pointer to a place where there are two int objects (and, because we know it is the first element of an array of two arrays of two int objects, we know there are two more int objects beyond the first two).
The definition of c with int **c means that c is a pointer to a pointer to an int. A pointer to a pointer and a pointer to an array are different and are not compatible.
One way to fix this is to define c with int (*c)[2] = malloc(2 * sizeof *c);. It is then unnecessary to have the loop after the definition that allocates more space; the single allocation allocates the entire array.
The return type of MultiArray should be changed similarly, as well as the code within it and elsewhere in the program. Alternatively, the second parameter of MultiArray can be changed from int b[2][2] to int **b. (This latter is an easier edit but produces an inferior program, since it uses more pointers and allocations than necessary.)
You should always compile your code with warnings enabled. That would have alerted you to the incorrect call.

Related

Matrix pointer in C

I will go straight to what I'm asking for, I also see some similar question but is not what I'm looking for...so it seems I have to ask with a new forum.
I'm preparing myself for a future examination, where is not required the pointer, but I would like to get some extra information and abilities.
Here's the code followed by the question...
I'm using Fedora 33, I know is different from some IDE on Windows (ex: Visual Studio or Dev C++)
/* It's just a simple test, if this work I will get myself into a more complicated one, as you could read in the
* forum, I'm getting ready ( just a recheck of my abilities ) for an universitary examinaton. */
#include <stdio.h>
#include <stdlib.h>
#define N 5
void casual_generation(int** mat);
void prompt_print(int** mat);
int main()
{
int **mat[N][N];
casual_generation(**mat);
prompt_print(**mat);
}
void casual_generation(int** mat)
{
int i=0,j=0;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
mat[i][j] = rand() % 50;
}
void prompt_print(int** mat)
{
int i=0,j=0;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
Somebody else on the forum used malloc, struct or other stuff, as you can see in this picture, when I try to execute him it says "Segmentation fault (core dumped)"
screen error
Where is my error?
And if you want, can you also send me the version with the passed value pointer?
Thanks for whoever will give me an answer, and time dedicated.
This declaration
int **mat[N][N];
does not make a sense. It means that you have a matrix elements of which are pointers of the type int **. But you need a matrix elements of which are integer numbers of the type int. That is you need a declaration like this
int mat[N][N];
So now you have a two-dimensional array (or matrix) of integers.
As you are going to pass this two-dimensional array to functions then used as an argument expression it is converted to pointer to its first element of the type int ( * )[N].
Correspondingly the functions that accepts such an array should be declared like
void casual_generation( int mat[][N], size_t n );
void prompt_print( int mat[][N], size_t n );
or (that is fully equivalent) like
void casual_generation( int ( * mat )[N], size_t n );
void prompt_print( int ( *mat )[N], size_t n );
because the compiler adjusts function parameters having array types to pointers to array element types.
Now for example the first function can be defined the following way
void casual_generation( int ( * mat )[N], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
mat[i][j] = rand() % 50;
}
}
}
And the function can be called like
casual_generation( mat, N );
A similar way can be defined the function prompt_print.
Using the second parameter makes the function more general. For example it can be called for two-dimensional arrays with different numbers of rows.
Now I will explain why you are getting a segmentation fault in your original code.
You have this declaration
int **mat[N][N];
a two dimensional array of pointers of the type int **.
Then you are using the expression **mat as an argument of function calls like this
casual_generation(**mat);
Then you are applying the dereference operator like *mat the array designator is converted to pointer to its first element (row) having the type int ** ( * )[N]. So dereferencing this pointer you get the first row of your array int **[N]. Applying the second time the dereferenced operator to this expression that has an array type the used expression is again is converted to pointer to its first element of the type int **( * ). That is it points to the first element of the first row of the original two-dimensional array. Dereferencing this pointer you get the first element of the type int **. This uninitialized pointer with indeterminate value the function accepts as its argument.
Thus dereferencing this first uninitialized element of the original matrix within the function
mat[i][j] = rand() % 50;
^^^
you get a segmentation fault. The reason of the fault is the incorrect matrix and the corresponding function parameter as it was shown above in tbe beginning of the answer.
Where is my error?
The "Segmentation fault" error happens because you define the variable mat as a pointer, but don't allocate any memory for it to point to.
int **mat[N][N];
You meant to do
Int mat[N][N];
and
casual_generation(mat);
prompt_print(mat);
By passing **mat you are passing mat[0][0] that is an int, but you want to pass the whole matrix which is a pointer to pointers to int (i.e. int **)
And you may want to introduce srand() in your code.
Just to make things clear:
mat is of type int ** and it's the whole matrix (or if you want it's a pointer to the first row)
*mat is of type int * and it's the first row of the matrix (or if you want it's a pointer to the first element of the first row)
**mat is of type int and it's the first element of the first row of the matrix
int **mat[N][N];
Here, you defined a double pointer to a 2D array. You only need to use one of those - a double pointer or a 2D array, like so:
int mat[N][N];
However, the bigger problem comes from trying to interchange 2D arrays and double pointers. This isn't possible in C since the 2D array is laid out flat in memory.
You need to create an array mat_ptr of pointers yourself and then pass that to casual_generation and prompt_print.
Finally, these casual_generation and prompt_print functions expect to be given a pointer, so you shouldn't dereference the pointer with ** before calling the function.
The final working code is:
int main()
{
int mat[N][N];
int *mat_ptr[N];
for (int i = 0; i < N; i++)
mat_ptr[i] = mat[i];
casual_generation(mat_ptr);
prompt_print(mat_ptr);
}
As you can find a detailed explanation why the code crashed in the other answer I will only propose a quite elegant solution that uses a neat though little known feature from C99 called Variable Length Arrays (aka VLA).
#include <stdio.h>
#include <stdlib.h>
void casual_generation(int n, int mat[n][n]);
void prompt_print(int n, int mat[n][n]);
int main()
{
const int N = 5;
int mat[N][N];
casual_generation(N, mat);
prompt_print(N, mat);
}
void casual_generation(int n, int mat[n][n])
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mat[i][j] = rand() % 50;
}
void prompt_print(int n, int mat[n][n])
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
It compiles in pedantic mode with no warnings and it works like a charm.
VLA were introduced to C to simplify numerical computation over multidimensional arrays.

C - parameter in function can't handle int if declared as int*

I want to use the C function called is_subsetOf() in two different ways:
Way 1: int* a and int* b are arrays with sizes >=2.
Way 2: int* a has size >=2, but int* b is only size 1, which means b is an int.
How can I force C to be okay with int* b being of size 1? Or is this not possible in C? An int IS an array of size 1??
int* is_in(int *left_hand, int n_l, int *right_hand, int n_r) {
int *get_bool;
get_bool = malloc(sizeof(int)*n_l);
for (int i=0; i<n_l; i++) {
if (is_subsetOf(right_hand, n_r, *(left_hand+i), 1)) {
*(get_bool+i) = 1;
}
}
return (get_bool);
}
int desc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int is_subsetOf(int *a, int n_a, int *b, int n_b) {
qsort(a, n_a, sizeof(int), desc);
qsort(b, n_b, sizeof(int), desc);
int v = includes(a, n_a, b, n_b);
return(v);
}
Here are the messages I get from the compiler. It's just a warning, I know, but I'd like everything to be clean.
tmp.c: In function ‘is_in’:
tmp.c:73:47: warning: passing argument 3 of ‘is_subsetOf’ makes pointer
from integer without a cast [-Wint-conversion]
if (is_subsetOf(right_hand, n_r, *(left_hand+i), 1)) {
~~~~~~~~~^~~
tmp.c:37:39: note: expected ‘int *’ but argument is of type ‘int’
int is_subsetOf(int *a, int n_a, int *b, int n_b) {
int* a and int* b are arrays with sizes >=2.
No, they are pointers and they don't have any size. You probably meant that you pass arrays through them, but they are not arrays. Know that there is a difference.
An int IS an array of size 1
No, int a[1]; is an array of size 1; int a; is just int. But arrays can decay into pointers to their first element and variables have addresses, so this is correct:
int a[1];
int b;
int* ptr1 = a;//Points to the a[0]
int* ptr2 = &b;
Both are now same type and can be used in the same way. Of course you don't know if the int is followed by any more ints in memory, that kind of checking is up to the programmer (usually by passing the length param as you do). The following is the code you are actually looking for:
is_subsetOf(right_hand, n_r, left_hand+i, 1)
Pointers can be incremented, left_hand+i will point to the i-th int after the int to which left_hand currently points to. Again, validity of such pointer is up to programmer.
The compiler warning is quite important here, because *(left_hand+i) is of type int and the compiler warns that it will treat is as int*. Essentially looking that the value of int as an address to memory. That's not at all what you want and it is an error.

C feeding array to function [duplicate]

Having looked around I've built a function that accepts a matrix and performs whatever it is I need on it, as follows:
float energycalc(float J, int **m, int row, int col){
...
}
Within the main the size of the array is defined and filled, however I cannot passs this to the function itself:
int matrix[row][col];
...
E=energycalc(J, matrix, row, col);
This results in a warning during compilation
"project.c:149: warning: passing argument 2 of ‘energycalc’ from
incompatible pointer type project.c:53: note: expected ‘int **’ but
argument is of type ‘int (*)[(long unsigned int)(col +
-0x00000000000000001)]’
and leads to a segmentation fault.
Any help is greatly appreciated, thank you.
The function should be declared like
float energycalc( float J, int row, int col, int ( *m )[col] );
if your compiler supports variable length arrays.
Otherwise if in declaration
int matrix[row][col];
col is some constant then the function can be declared the following way
float energycalc(float J, int m[][col], int row );
provided that constant col is defined before the function.
Your function declaration
float energycalc(float J, int **m, int row, int col);
is suitable when you have an array declared like
int * matrix[row];
and each element of the array is dynamically allocated like for example
for ( int i = 0; i < row; i++ ) matrix[i] = malloc( col * sizeof( int ) );
If the array is declared as
int matrix[row][col];
then change the function declaration to
float energycalc(float J, int m[][col], int row, int col){
The name of a two dimensional array of type T does not decay to T**.
If col is a local variable, then you need to call the function with the col parameter before matrix. This is done so that col is visible in the function.
Passing two dimensional array to a function in C is often confusing for newbies.
The reason is that they assume arrays are pointers and having lack of understanding how arrays decays to pointer.
Always remember that when passed as an argument arrays converted to the pointer to its first element.
In function call
E = energycalc(J, matrix, row, col);
matrix is converted to pointer to its first element which is matrix[0]. It means that passing matrix is equivalent to passing &matrix[0]. Note that the type of &matrix[0] is int(*)[col] (pointer to an array of col int) and hence is of matrix. This suggest that the second parameter of function energycalc must be of type int(*)[col]. Change the function declaration to
float energycalc(int col, int (*m)[col], int row, float J);
and call your function as
E = energycalc(col, matrix, row, J);
I think you can do something like this in C
float function_name(int mat_width, int mat_height, float matrix[mat_width][mat_height]) {
... function body...
}
A pointer-to-pointer is not an array, nor does it point to a two-dimensional array. It has nothing to do with arrays, period, so just forget you ever heard about pointer-to-pointers and arrays together.
(The confusion likely comes from the hordes of confused would-be programming teachers/authors telling everyone that they should use pointer-to-pointer when allocating dynamic 2D arrays. Which is just plain bad advice, since it will not allocate a real array allocated in adjacent memory cells, but rather a fragmented look-up table exploded in pieces all over the heap. See this for reference about how to actually allocate such arrays.)
Assuming that your compiler isn't completely ancient, simply use a variable length array (VLA), which is a feature introduced in the C language with the C99 standard.
#include <stdio.h>
void print_matrix (size_t row, size_t col, int matrix[row][col]);
int main (void)
{
int matrix[2][3] =
{
{1,2,3},
{4,5,6}
};
print_matrix(2, 3, matrix);
return 0;
}
void print_matrix (size_t row, size_t col, int matrix[row][col])
{
for(size_t r=0; r<row; r++)
{
for(size_t c=0; c<col; c++)
{
printf("%d ", matrix[r][c]);
}
printf("\n");
}
}

how to copy returned array directly into another array?

I have been learning arrays, but theres one thing that I cant figure out.
I borrowed two books for C and looked online, but found no solution.
My function timesTen multiplies every array elemenet that I have by 10,
then returns pointer of that array back function main()
How can I copy array a[2] directly in array x[2]?
I would usually use for loop, but I cant, because arguments are in two different functions.
Solution has probably got something to do with pointers, so feel free to post sollution here, but is there any way around them aswell?
Heres the source code:
#include <stdio.h>
int timesTen(int a[])
{
int i;
for (i=0;i<2;i++)
{
printf("%d\t", a[i]);
a[i]*=10;
printf("%d\n", a[i]);
}
return a;
}
int main()
{
int i;
int x[2];
int a[2]={10,50};
// i know here's an error, but how do I fix it? I cant put x[0]=timesTen(a[0])
x[2] = timesTen(a);
//also what if there is array a[10], and I want to copy it in x[5]
for (i=0;i<2;i++)
printf("%d\n", x[i]);
return 0;
}
Thanks!
What you need to understand is the distinction between arrays and pointers. When you declare your two arrays in main(), you allocate two times memory for two integers. That's fine. But in C, you simply cannot pass arrays around (as in: implicitly allocate a new slap of memory and copy the data of the source array into this memory region). Instead, any array identifier will decay to a pointer to the first element of the array in almost all situation. So when you write
int x[2];
int a[2]={10,50};
timesTen(a);
this code is precisely equivalent to
int x[2];
int a[2]={10,50};
timesTen(&a[0]);
So, why does that not clash with your declaration of timesTen()? Because array parameters in function declarations decay right there, on the spot, into a pointer! So, your function declaration is precisely equivalent to this one:
int timesTen(int* a) {
This is one of the least understood features of the C language, and admittedly, it is hard to wrap your brain around this, but once you understand what pointer decay means, you will be much more at ease using pointers and arrays.
So, back to your question. Since you passed only a pointer to your array to timesTen(), and since you modify this array, the changes are directly visible in main(). There are two ways to achieve the behavior you want:
You can change the definition of timesTen() to copy the data into a destination array:
void timesTen(int size, int* source, int* dest) {
for(int i = 0; i < size; i++) dest[i] = 10*source[i];
}
int main() {
int x[2];
int a[2]={10,50};
timesTen(2, a, x); //pointer decay!
//x now contains {100, 500}
}
You can copy the data into the destination array before calling your function to modify the destination array:
void timesTen(int size, int* data) {
for(int i = 0; i < size; i++) data[i] = 10*data[i];
}
int main() {
int x[2];
int a[2]={10,50};
memcpy(x, a, sizeof(a)); //the sizeof operator is one of only two places where no pointer decay happens!
timesTen(2, x); //pointer decay!
//x now contains {100, 500}
}
In the function timesTen, since a is an array, each modification made to it in the function is also done to the parameter you passed (call by address not by value). Therefore you don't need to returns anything.
void timesTen(int a[])
{
int i;
for (i=0;i<2;i++) a[i]*=10;
}
And you just call it by:
timesTen(a);
You probably want something like this:
timesTen(a);
memmove(x, a, 2 * sizeof(x[0]));
instead of
x[2] = timesTen(a);
Note that your function does not need to return anything, because it is modifying the array on its original place. In C if you have an array parameter, it means that only a pointer is passed, not the whole array.
in main function:
int *p;
int i;
p = timesTen(a);
for ( i = 0; i < 2; i++ )
{
printf( "%d\n",*(p + i)); // here you can print the values returned from your function
}
Through pointers you could have eaisly managed it
main ()
{
int a[ 2 ];
int *ptr = timesTen(a);
for ( int i=0; i<2 ; i++)
{
printf("%d",ptr[i]);
}
And as far as
x[2] = timesTen(a);
Is concerned note that x[2] will give "value at 2nd adress from adrees of base that is x"
And it is not a variable but it is a value and you cant assign to a value.
Technically x[2] is not a lvalue.

how to get the value from the array in C?

I have a two dimensional array like this:
void getC(int **p)
{
*p = &c[0][0];
}
int c[10][10];
int *a;
getC(a);
a[0][0];
it says error: no match for 'operator[]' in `a[0][0];` what is the problem and how to fix it?
You're compiling a C program with a C++ compiler. Watch out!
You need to put the definition of c above the getC function (or provide a forward declaration).
You have statements outside of a function, which isn't allowed in C. Wrap the int *a and subsequent lines with int main(void) { ... }
You need a & to make your getC() call legal - you're passing an int *, but it expects int **:
getC(&a);
The statement a[0][0] has no effect, and is anyway wrong since a is just an int *; you can't dereference it twice.
You should probably get a beginner C book and start working through it.
Essentially you are sort of downgrading the array/pointer from an int (*)[10] (pointer to array of 10 int) to a simple int pointer, by just returning the address of the first element of the 2dim array. While this is techically correct (the address of one element of the 2dim array is of course an int*), the information about the structure/layout of the ints in the array is lost, so the resulting a-ptr doesn't now anything about the fact that the int was part of a [10][10] structure.
In your case, the only way to get to the array elements would be to multiply your way through the int arrays, based on your own knowledge that at address a there are 100 ints organized 10x10:
int *a;
getC(&a);
...= a[10*x + y]; // equivalent of c[x][y];
.
However, essentially, the correct way (completely preserving types) would be
int c[10][10];
void getC(int (**p)[10]) // pointer to pointer to array of 10 ints
{
*p = c; // c itself can seamlessly change into a pointer to one sub-element
// (i.e. pointer to array of 10)
}
int main()
{
int (*a)[10]; // pointer to array(s) of 10 ints
int q;
getC(&a);
q= a[9][9];
...
}
The same again with one more dimension level (probably the most intutive solution):
However, essentially, the correct way (completely preserving types) would be
int c[10][10];
void getC(int (**p)[10][10]) // pointer to pointer to array of 10x10 ints
{
*p = &c; // &c can seamlessly change into a pointer to 10x10 ints
}
int main()
{
int (*a)[10][10]; // pointer to array(s) of 10x10 ints
int q;
getC(&a); // pass adress of pointer to 10x10 ints
q= (*a)[9][9]; // need *a in brackets to derference the pointer (operator precedence)
...
}

Resources