How to write a square matrix multiplication function in C? [duplicate] - c

This question already has answers here:
How to pass 2D array (matrix) in a function in C?
(4 answers)
Closed 1 year ago.
int Ma_Multiplication(int A[][], int B[][], int size){
int C[size][size];
for( i = 0 ; i< size ; ++i){
for( j=0 ; j< size ; ++j){
C[i][j] = 0;
for( k = 0 ; k < size; ++k)
C[i][j] = C[i][j] + (A[i][k]*B[k][j]);
printf("%d ",C[i][j]);
printf("\n");
}
}
I wrote this function to calculate multiplication of 2 matrices. But when I debugged, it told me this:
error: array type has incomplete element type 'int[]'
4 | int MATRIX(int A[][], int size){
| ^
Could anyone can explain this? Thank u so much!

C does not allow declaration of arrays with element of incomplete type. Thus int A[] is ok. However, int A[][] is not because it's element type is int[] which is incomplete.
To fix I suggest fully defining the parameters using VLA types:
int Ma_Multiplication(int size, int A[size][size], int B[size][size]) {
...
}
If you want to keep an original ordering of parameters you must use an extension (GCC and CLANG) allowing to declare the parameters.
int Ma_Multiplication(int size; int A[size][size], int B[size][size], int size)
This extension may get mainlined into upcoming C23 standard

Related

defining 2D array in c in VS Express 2012

#include<stdio.h>
void main()//this is the way that we pragram in c
{
int arr[][]={{1,2},{1,2},{1,3}};//in class it wasnt required to initialize both
}
the errors:
Error 1 error C2087: 'arr' : missing subscript
Error 2 error C2078: too many initializers
3 IntelliSense: an array may not have elements of this type
I am a beginner , and i saw in class that the professor did the same thing.
also i asked my instructor and he told me that it should raise this error.
can someone please addres me to where and what is the problem?
You're missing the type; all but the first dimension must be specified; and you're missing commas between the aggregate initializers. Working example:
int main(void) {
int arr[][2] = {{1,2}, {1,2}, {1,3}};
}
When you have such a declaration
int arr[][]={{1,2},{1,2},{1,3}};
then the compiler can determine the number of the elements for the left most dimension. There are three initializers so the left most dimension is equal to 3. However the compiler is unable to determine the number of elements in the right most dimension because all these declarations are valid
int arr[][2]={{1,2},{1,2},{1,3}};
int arr[][20]={{1,2},{1,2},{1,3}};
int arr[][200]={{1,2},{1,2},{1,3}};
So you need explicitly to specify the number of elements in the right most dimension of the array. As I can guess you mean the following array declaration
int arr[][2]={{1,2},{1,2},{1,3}};
that is equivalent to
int arr[3][2]={{1,2},{1,2},{1,3}};
Though the MS VS allows a declaration of main like
void main()
nevertheless according to the C Standard the function main without parameters shall be declared like
int main( void )
even if a rerun statement is absent.
You should add type to your array declaration - for example int arr[][].
If you don't want to specify size of columns and rows you have to do it dynamically. For example this way:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r = 3, c = 4, i, j, count;
int **arr = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // OR *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d ", arr[i][j]);
/* Code for further processing and free the
dynamically allocated memory */
return 0;
}

Why passing 2D matrix gives error in C?

I have written this below simple code to demonstrate passing 2D matrix in C. I have gone through most of the online articles. And this code is inaccordance with those suggested approaches. But still I am getting a compile error. Please explain.
#include <stdio.h>
int max = 0;
void maxId(int i,int j, int p[8][12]){
}
int main(){
int m = 8;
int n = 12;
int p[m][n] = {{0,1,1,0,1,0,0,0,1,1,1,0},
{0,1,1,0,1,0,0,0,1,1,1,0},
{0,0,1,0,1,0,0,0,1,1,1,0},
{0,1,0,0,1,1,1,0,1,1,1,0},
{0,0,1,0,1,0,1,0,1,1,1,0},
{0,0,1,0,1,0,1,0,1,1,1,0},
{0,1,0,0,1,1,0,0,1,1,1,0},
{0,0,1,0,1,0,0,0,1,0,1,1}};
int v[m][n];
for(int i= 0;i<m;i++)
for(int j = 0;j<n;j++){
v[i][j] = v[i][j];
}
maxId(0,0,p);
return 0;
}
Updated
The compile error shown is
29 13 C:\Users\RainDrop\Documents\devc++
projects\Untitled2.cpp [Error] cannot convert 'int ()[n]' to 'int
()[12]' for argument '3' to 'void maxId(int, int, int (*)[12])'
I see couple of problems:
A VLA, such as p, cannot be used as an argument to a function that expects a fixed size array. Imagine the problems if m is not 8 or n is not 12.
A VLA cannot be initialized using an intializer list.
You can solve both problems by making m and n macros.
#define m 8
#define n 12
If you choose to do that, replace the use of the hard coded value 8 and 12 by m and n, respectively, everywhere.
Update to point 1 above
gcc does not mind if a VLA is used an argument in a function call where the expected argument type is fixed array. i.e. it is OK using int (*)[n] when the argument type is int (*)[12]. I have not been able to find anything in the standard that indicates which compiler is correct.
To get around the issues mentioned by R Sahu's answer, you can do the following:
#include <stdio.h>
void maxId(size_t m,size_t m, int p[m][n]){
}
#define M (8)
#define N (12)
int main(void)
{
int p[M][N] =
{
{0,1,1,0,1,0,0,0,1,1,1,0},
{0,1,1,0,1,0,0,0,1,1,1,0},
{0,0,1,0,1,0,0,0,1,1,1,0},
{0,1,0,0,1,1,1,0,1,1,1,0},
{0,0,1,0,1,0,1,0,1,1,1,0},
{0,0,1,0,1,0,1,0,1,1,1,0},
{0,1,0,0,1,1,0,0,1,1,1,0},
{0,0,1,0,1,0,0,0,1,0,1,1}
};
size_t n = N;
size_t m = M;
int v[m][n];
for (size_t i = 0; i < m; i++)
{
for(size_t j = 0; j < n; j++)
{
v[i][j] = p[i][j];
}
}
maxId(m, n, v);
return 0;
}

Function passing of multidimensional array in c

#include <stdio.h>
void spiral(int a[10][10]) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int a[r][c];
for (i = 0; i < r; i++)
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
spiral(a);
return 0;
}
When I give a 3 x 6 array
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
The output is 14, while it should be 10
How to fix this issue?
If you enter 3 and 6 for r and c (respectively) then the type of a is not int[10][10] (or int(*)[10] as the spiral argument really is), it's int[3][6]. The memory layout is completely different for the arrays, leading to undefined behavior.
You can solve this by passing the size along to the function, and using it in the declaration of the array:
void spiral(const size_t r, const size_t c, int (*a)[c]) { ... }
Call it like expected:
spiral(r, c, a);
As noted using int a[r][c] as argument might be easier to read and understand, but it gives a false impression that a is actually an array. It's not. The compiler treats the argument as a pointer to an array of c integers, i.e. int (*a)[c].
This makes me a little conflicted... On the one hand I'm all for making things easier to read and understand (which means it will be easier to maintain), on the other hand newbies often get it wrong and think that one can pass an array intact when in fact it decays to a pointer which can lead to misunderstandings.
A few things are wrong: in void spiral() you ask for a 2D-array of 10*10, but you do not give that. Keep that part as a variable, so only ask the type you receive and not what you want to receive and with creating a dynamic array you should always do that with malloc or calloc and free them afterwards. This might be a bit hard at first, but when you start creating bigger programs this is a must if you have a question or do not understand the pointers in the program called (*) then ask me:
#include <stdio.h>
#include <stdlib.h>
void spiral(int **a) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int **a = malloc(r * sizeof(int*));
for (i = 0; i < r; i++) {
a[i] = malloc(c * sizeof(int));
}
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
}
spiral(a);
for (i = 0; i < r; i++) {
free(a[i]);
}
free(a);
return 0;
}

Warning: Expected ‘int **’ but argument is of type ‘int (*)[(sizetype)(n)]’ [duplicate]

This question already has answers here:
How is memory allocated for an implicitly defined multidimensional array in C99?
(4 answers)
Passing a multidimensional variable length array to a function
(2 answers)
Closed 9 years ago.
Following code:
#include <stdio.h>
void printSpiral(int **M, int row1, int row2, int col1, int col2) {
if (!((row1 <= row2) && (col1 <= col2)))
return;
int i;
for (i = col1; i <= col2; i++)
printf("%d ", M[row1][i]);
for (i = row1; i <= row2; i++)
printf("%d ", M[i][col2]);
for (i = col2; i >= col1; i--)
printf("%d ",M[row2][i]);
for (i = row2; i >= row1; i--)
printf("%d ",M[i][col1]);
printSpiral(M,row1+1,row2-2,col1+1,col2-1);
}
int main() {
int n;
scanf("%d",&n);
int M[n][n];
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d",&M[i][j]);
printSpiral(M,0,n-1,0,n-1);
return 0;
}
gives following warning:
spiral.c: In function ‘main’:
spiral.c:26:3: warning: passing argument 1 of ‘printSpiral’ from incompatible pointer
type [enabled by default]
printSpiral(M,0,n-1,0,n-1);`
spiral.c:3:6: note: `expected ‘int **’ but argument is of type ‘int (*)[(sizetype)(n)]’`
void printSpiral(int **M, int row1, int row2, int col1, int col2) {
I have seen this warning for the first time. What does it mean?
There are two problems with this code. First you are passing argument of int (*)[(sizetype)(n)] (pointer to an array of n integers, this is the type your 2D array M decays to when you pass it to a function) to your function which is expecting an argument of int **. Always remember Arrays are not pointers. One possible solution is you can change your function's first parameter to int (*)[(sizetype)(n)] type.
void printSpiral(int (*M)[n], int row1, int row2, int col1, int col2) {
But by doing this the second problem will comes into light and that is because of you declared M as variable length array and n is not known to the function. This issue can be resolved by passing n from main to your function and hence change your function definition to
void printSpiral(int n, int (*M)[n], int row1, int row2, int col1, int col2) {
The compiler wants to tell you that the functions expects a int **, but you provide it an argument of type int (*)[(sizetype)(n)].
The first is a pointer to (the first element of an array of) int *, the second one is a pointer to an array/arrays of given length.
Compare what both means in memory and why this cannot work this way.
The solution would be to provide the function a pointer to one element an at least the total number of columns. (If you want the function to do bounds-checking, it needs the number of rows as well.) Then you have to calculate the indexes manually.
you should know int a[][] is different from int **a,the first a is same to int (*a)[] which means a pointer which point a array;if you want to indicate a 2D array by int **a,please reference this:C Programming: Initialize a 2D array of with numbers 1, 2, 3

C programming confused with output [duplicate]

This question already has answers here:
Weird behavior when printing array in C?
(5 answers)
Closed 9 years ago.
Can anyone please explain the output for the following program? I get an infinite loop if used a[i] = 0; and a segfault when I used a[i] = i; and also the i ranges between 0 - 9 when used a[i] = 0; whereas it goes to 39 when used a[i] = i; before giving a segfault.
#include<stdio.h>
#include<stdlib.h>
int mult(int a, int b);
int main()
{
int a[10];
int i = 0;
for(i=0; i < sizeof(a); i++)
{
a[i] = i;
printf("a[i]=%d i=%d\n", a[i], i);
}
return 0;
}
When you apply the sizeof operator to an array type, the result is the total number of bytes in the array, i.e, sizeof(a) determines the number of bytes in a which is not the number of elements in the array in this case. Use sizeof(a)/sizeof(a[0]) to get number of elements in the array a.
Replace
for(i=0;i<sizeof(a);i++)
with
for(i=0;i<sizeof(a)/sizeof(a[0]);i++)
Also, no need to initialize i twice.
You probably want to change this line:
for(i=0;i<sizeof(a);i++)
to this:
for(i=0;i<sizeof(a)/sizeof(a[0]);i++)
Note:
sizeof(a) gives the number of bytes in a[].
sizeof(a)/sizeof(a[0]) gives the number of elements in a[].
sizeof doesn't do what you think it does. It's returning the number of bytes occupied by the entire array.
You want the numeric length of the array, not the byte size.
Try something like this:
const int array_size = 10;
int a[array_size];
for (int i = 0; i < array_size; i++) {
a[i] = i;
printf("a[%d] = %d\n", i, a[i])
}
If you want to know how far to loop, without storing it in a separate const, use sizeof(a)/sizeof(a[0])

Resources