Matrix in C: is that functions share local variables? - c

I defined as a global variable in int main() a matrix a[][], i didn't initialised the variable.
Then I used some function:
The first one: receives as argument the matrix a and then defines a[i][j] as a certain value (random), this for all i and j in the appropriate range. The function simply returns 1;
The second one: receives as argument the matrix a and simply prints it. Also this function simply returns 1;
The last one: receives as argument the matrix a and then determines the maximum of its values and return that values
I thought, naively, that writing plainly the code without defining some pointer to the matrix, to make the variable of the matrix global and sharable from all the functions, the code simply wouldn't have worked. But it worked.
I thought that it wouldn't have worked because i didn't defined the matrix in a global way, but it is defined only in a function and then (to me:)pretends to pass to the other functions.
So my question is: why it worked?
The code:
int matrix_definition(int a[][], int dim);
int matrix_print(int a[][], int dim);
int max_matrix(int a[][],int dim);
int main()
{
int a[][], dim;
matrix_definition(a,dim);
matrix_print(a,dim);
printf("%d", max_matrix(a,dim));
return 0;
}
The full code including main() and matrix_definition is this:
#include<stdio.h>
#define SIZE 100
int matrix_definition(int a[SIZE][SIZE], int dim);
int matrix_print(int a[SIZE][SIZE], int dim);
int max_matrix(int a[SIZE][SIZE],int dim);
int main()
{
int a[SIZE][SIZE], dim;
matrix_definition(a,dim);
matrix_print(a,dim);
printf("%d", max_matrix(a,dim));
return 0;
}
int matrix_definition(int a[SIZE][SIZE],int dim)
{
int i,j;
srand(time(NULL));
for(i=0;i<dim;i++)
{
for(j=0;j<dim;j++)
{
a[i][j]=rand()%2;
}
}
return 1;
}

The updated code you posted is very different from what you originally posted. Yes, that code is valid with regard to how a is defined and how it is passed to various functions.
In each of your function declarations you declare a parameter:
int a[SIZE][SIZE]
Since arrays as parameters are converted to pointers, this is equivalent to:
int (*a)[SIZE]
This is compatible with the variable defined in main:
int a[SIZE][SIZE];
When passing an array to a function, it decays to a pointer to the first element. So this function call:
matrix_definition(a,dim);
is the same as:
matrix_definition(&a[0],dim);
The expression a[0] has type int [SIZE], so the expression &a[0] has type int (*)[SIZE]. This is the same as the function's parameter.

Related

Array has incomplete element type. What does this mean? [duplicate]

This question already has answers here:
Why do we need to specify the column size when passing a 2D array as a parameter?
(8 answers)
Closed 2 years ago.
I want to create an array that has that stores the multiplication values of any integer n. After that, I would like to pass that array into another function and print out the array. However, I get the following error:
My code:
This is my .c file:
#include "multiplication.h"
#include <stdio.h>
int main(){
int num;
int arr=multiplication(4);
printArray(arr);
}
int mulitpication(int num){
/* initialize array and build*/
int arr[num][num];
for(int i=0; i<num;i++){
printf("row number: %d ",i);
for(int j=0;j<num;j++){
printf("column number: %d", j);
arr[i][j]= (i+1)*(j+1);
}
}
return arr;
}
void printArray(int arr[][]){
int i;
for(i=0;i<sizeof(arr);i++){
for(int j=0;j<sizeof(arr);j++){
printf("%d ",arr[i][j]);
}
}
This is my header file:
void multiplication(int num);
void print(int arr[][]);
The Error:
multiplication.h:4:19: error: array has incomplete element type 'int []'
void print(int arr[][]);
^
First of all, you don't include the source files into one another, you compile and link them together to form the binary.
That said, the actual problem is in the code you did not show (multiplication.h file), but from the error message we can see
void print(int arr[][]);
is not a valid syntax. You can only leave the outer(-most) index as empty, all other index(es) must have a proper value. Something like
void print(int arr[ ][10]);
^^---------- inner index
^^^------------- outer index
or, for more dimensions
void print(int arr[ ][5][10][15]);
The analogy behind this is, for function declarators,
"A declaration of a parameter as ''array of type'' shall be adjusted to ''qualified pointer to type'',...."
So, to have that adjustment, the type should be known to compiler at compile-time.
In case of a declaration like
void print(int arr[][10]);
the type is int[10], but if a syntax like
void print(int arr[][]);
is allowed , the type cannot be known. Hence the error.
Other issues: You seem to have many other issues, like
The function definition is
int mulitpication(int num){ // returning an int
but actually you do
return arr; //where arr is an array of size int[num][num], defined locally
this is invalid because of two things
an int and an int[num][num] are not the same type.
the scope of a VLA i.e., arr is limited to the function block, you cannot have the array return the address to the caller and expect something meaningful as the returned address will not be valid anymore.
I believe, you're better off using allocated memory (malloc() and family) and keeping track of your index/ count of elements manually.
To fix the printArray function you will need to include the array dimensions. In C, arrays are simply a block of elements, there is no length stored anywhere. The programmer would need to keep track of the length by some method.
For example:
// header
void printArray(int num, int arr[num][num]);
// source file
void printArray(int num, int arr[num][num])
{
for(int i=0;i<num;i++){
for(int j=0;j<num;j++){
printf("%d ",arr[i][j]);
}
For the multiplication function you will need to do something similar, the caller should allocate the array (e.g. int arr[num][num];) and then the function should fill in the values for the array cells.

What does "[*]" (star modifier) mean in C? [duplicate]

This question already has answers here:
Why use an asterisk "[*]" instead of an integer for a VLA array parameter of a function?
(2 answers)
Closed 6 years ago.
While trying to implement a C11 parser (for educational purposes), I found that in C11 (p. 470) but also in C99 (p. 412) (thanks Johannes!), the direct declarator is defined as:
(6.7.6) direct-declarator:
direct-declarator [ type-qualifier-list? * ]
At first, I thought this was an error in the grammar (the type list shouldn't be optional). However, when I tried this out in my reference compiler (clang), I got an rather unexpected error:
int array[*] = { 1, 2, 3 };
// error: star modifier used outside of function prototype
So apparently, (in clang) this is called the star modifier.
I quickly learned that they can only be used in function signatures:
void foobar(int array[*])
However, they can only be used in the declaration. Trying to use it in a function definition results in an error as well:
void foobar(int array[*]) {
// variable length array must be bound in function definition
}
So as far as I can tell, the intended behaviour is to use [*] in the function declaration and then use a fixed number in the function definition.
// public header
void foobar(int array[*]);
// private implementation
void foobar(int array[5]) {
}
However, I have never seen it and I don't quite understand the purpose of it either.
What is its purpose, why was it added?
What's the difference with int[]?
What's the difference with int *?
What is its purpose, why was it added?
Purpose is seen when a variable length two dimentional array is used as a function parameter. The function
int foo(int n, int m, int a[n][m]) {...}
can be prototyped as any of the following
int foo(int , int, int [][*]);
int foo(int , int, int a[*][*]);
int foo(int , int, int (*a)[*]);
int foo(int n, int, int a[n][*]);
int foo(int , int m, int a[*][m]);
int foo(int , int m, int (*a)[m]);
int foo(int n, int m, int a[n][m]);
In case of two dimensional array, when used as function parameter, size of the second dimension can't be omitted. If the name of first variables in function prototype is omitted then it wouldn't be possible to specify the length (second dimension) of the array. The * gives the clue that the length of the array will be determined by the second parameter.
What's the difference with int[]?
What's the difference with int *?
In case of 1D array, for the function definition
int bar(int n, int a[n]} {...}
any of the following prototype is valid
int bar (int , int *);
int bar (int , int [*]);
int bar (int , int []);
int bar (int n, int a[]);
int bar (int n, int a[n]);
int bar (int n, int [n]);
In this case neither * nor n is necessary as compiler will treat both of int [*] and int [n] as int *. So, with one dimensional array you can't see much difference.
NOTE: When using variable length array as a function parameter, order of parameter is important. Order of parameters for first four prototypes of bar can be switched, but in latter two first parameter must not be the array itself.
int bar (int a[n], int n); //Wrong. Compiler has not yet seen 'n'.
The C rationale document for C99 says
A function prototype can have parameters that have variable length array types (ยง6.7.5.2) using a special syntax as in
int minimum(int, int [*][*]);
This is consistent with other C prototypes where the name of the parameter need not be specified.
What's the difference with int[]
What's the difference with int *.
I think it's simply that those types in a function prototype means "pointer", while a [*] in a non-top position (int[*] still equals int[] I think, in a function prototype) actually is valid and means array
// not recommended though: it is now unclear what the parameters
// mean to human callers!
void f(int, int [][*]);
void f(int n, int x[][n]) {
x[1][0] = 1;
}
int main() {
int a[2][1];
f(1, a);
printf("%d\n", a[1][0]);
}
As for the purpose, when indexing the array in the function definition, the compiler needs to know how many integers of the next index to skip when giving the first index (x[i] skips i * n integers in f above). But this information is not needed in the non-defining prototype declaration, hence it can be left out and replaced by *.

Passing a multidimensional array of variable size

I'm trying to understand what "best practice" (or really any practice) is for passing a multidimensional array to a function in c is. Certainly this depends on the application, so lets consider writing a function to print a 2D array of variable size. In particular, I'm interested in how one would write the function printArry(__, int a, int b) in the following code. I have omitted the first parameter as I'm not exactly sure what that should be.
void printArry(_____, int a, int b){
/* what goes here? */
}
int main(int argc, char** argv){
int a1=5;
int b1=6;
int a2=7;
int a2=8;
int arry1[a1][b1];
int arry2[a2][b2];
/* set values in arrays */
printArry(arry1, a1, b1);
printArry(arry2, a2, b2);
}
The easiest way is (for C99 and later)
void printArry(int a, int b, int arr[a][b]){
/* what goes here? */
}
But, there are other ways around
void printArry(int a, int b, int arr[][b]){
/* what goes here? */
}
or
void printArry(int a, int b, int (*arr)[b]){
/* what goes here? */
}
Compiler will adjust the first two to the third syntax. So, semantically all three are identical.
And a little bit confusing which will work only as function prototype:
void printArry(int a, int b, int arr[*][*]);
This is not really an answer, but extended comment to the OP's comment question, "well you can pass the array without knowing the number of rows with this, but then how will you know when to stop printing rows?"
Answer: generally, you can't, without passing the array size too. Look at this 1-D example, which breaks the array size.
#include <stdio.h>
int procarr(int array[16], int index)
{
return array[index];
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100));
return 0;
}
Program output (although all elements initialised to 0):
768
That was undefined behaviour and there was no compiler warning. C does not provide any array overrun protection, except for array definition initialisers (although such initialisers can define the array length). You have to pass the array size too, as in
#include <stdio.h>
int procarr(int array[16], size_t index, size_t size)
{
if (index < size)
return array[index];
return -1; // or other action / flag
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100, sizeof arr / sizeof arr[0]));
return 0;
}
Program output:
-1

Pass a 2D char array to a function in C

I'm a beginning programmer who is confused with passing a two dimensional array to a function. I think it may just be a simple syntax problem. I've looked for an answer, but nothing I've found seems to help, or is too far above my level for me to understand.
I identify the array and the function in the main function as, and after initializing it, attempt to call it:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int const ROWS = 8;
int const COLS = 8;
int main(int argc, char** argv) {
char board[ROWS][COLS];
bool canReach(char board[][], int i, int j);
//initialize array
//values of i and j given in a for loop
canReach(board, i, j);
return (EXIT_SUCCESS);
}
While writing the function outside the main function, I defined it exactly the same as I did in the main function.
bool canReach(char board[][], int i, int j){
//Functions purpose
}
When I attempt to build the program, I'm given this error twice and the program does not build:
error: array has incomplete element type 'char[][]'
bool canReach(char board[][], int i, int j)
^
Please note that I'm trying to pass the entire array to the function, and not just a single value. What can I do to fix this problem? I would appreciate it if it didn't have to use pointers, as I find them quite confusing. Also, I've tried to leave out things that I thought weren't important, but I may have missed something I needed, or kept in things I didn't. Thank you for your time in helping out this starting programmer!
You can just pass arrays as function arguments with definition of their size.
bool canReach(char board[ROWS][COLS], int i, int j);
When the size is unknown, pointers are the way.
bool canReach(char* board, int i, int j);
You should know, that arrays != pointers but pointers can storage the address of an array.
Here is a demonstrative program
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool canReach( int n, int m, char board[][m] )
{
for ( int i = 0; i < n; i++ )
{
for ( int j = 0; j < m; j++ )
{
board[i][j] = 0;
}
}
return printf( "Hello SaarthakSaxena" );
}
int main( void )
{
const int ROWS = 8;
const int COLS = 8;
char board[ROWS][COLS];
canReach( ROWS, COLS, board );
return EXIT_SUCCESS;
}
Its output is
Hello SaarthakSaxena
Defining a function inside another function (here: main) is not allowed in C. That is an extension of some compilers (e.g. gcc), but should not be used.
You have to specify the dimension of the array. C arrays do not have implicit size information as in HLL.
It also is not a good idea to use const variables for array dimensions in C. Instead
#define ROWS 8
#define COLS 8
Assuming i and j are the indexes of an element in the array, you can use the signature:
bool canReach(size_t rows, size_t cols, char board[rows][cols],
size_t i, size_t j);
This allows to pass arrays of (run-time) variable size to the function. If the dimensions are guaranteed fixed at run-time:
bool canReach(char board[ROWS][COLS], size_t i, size_t j);
But only if using the macros above. It does not work with the const variables.
Both versions tell the compiler which dimension the array has, so it can calculate the address of each element. The first dimension might be omitted, but there is nothing gained and it would imhibit optional bounds checking (C11 option). Note the 1D-case char ca[] is just a special version of this general requirement you can always omit the left(/outer)most dimension.
Note I changed the types to the (unsigned) size_t as that is the appropriate type for array-indexing and will generate a conversion warning if properly enabled (strongly recommended). However, you can use int, but have to ensure no value becomes negative.
Hint: If you intend to store non-character integers in the array or do arithmetic on the elements, you should specify the signed-ness of the char types. char as such can be either unsigned or signed, depending on implementation. So use unsigned char or signed char, depending what you want.

function call and function prototype in c with a 2d array parameter

void setup_map (int *map); <--- prototype
int row, col; <-- global variables
some main
{
//get number of rows and cols from user
int map[rows][cols]; //create map here because another function uses it
setup_map (map[row][col]);
}
void setup_map (int map[row][col])
{
loop through and set up map
}
my problem is I cant get the prototype quite right I was hoping somewhere could explain to me what my prototype needs to be? I have just begun learning about pointers and understand the concept pretty well just haven't ever used a 2d array as a argument. Thanks for any help.
Correct prototypes include:
void setup_map(int map[ROWS][COLS]);
void setup_map(int map[][COLS]);
void setup_map(int (*map)[COLS]);
And to call it:
setup_map(map);
Note that, however, that the number of rows and columns needs to be a compile-time constant for this to work.
There are several things wrong.
First thing wrong, you are calling your function in the wrong manner.
You should not call setup_map (map[row][col]); instead you should call setup_map (map); because the array name is a pointer, array name plus [] operator fetches the contents of a particular place on the memory.
Then you need to make your prototype and your definition look the same, because the compiler will use the prototype (not the definition, if it is later) to parse if your code is correct, and will conclude things wrong if your prototype is wrong.
Now on the prototype itself:
If you REALLY need your function to expect a fixed size array, then you must use compile time constants.
Like this:
void setup_map( int map[23][9]);
or this:
#define ROWS = 23;
#define COLS = 9;
void setup_map( int map[ROWS][COLS] );
Remember that the name of the array, is a pointer.
heres an example
#include <stdio.h>
void print_matrix(int x, int y, int matrix[][x])
{
int i, j;
for (i = 0; i < y; ++i) {
for (j = 0; j < x; ++j) {
printf("[%i]", matrix[i][j]);
}
putchar('\n');
}
}
int main()
{
int matrix[][2] = {{0, 1}, {2, 3}};
print_matrix(2, 2, matrix);
return 0;
}
you have to give integer values while declearing an array in the way you do.
such as:
int map[5][10];
if you would like to give these values as row and col, first you have to define macros for row and cols.
macros:
#define ROW 5
#define COL 10
declaration in main():
int map[ROW][COL];
if you are planning to take row and col values from the user, things may get a little complicated because then you have to do dynamic memory allocation by using malloc() and free() functions.
int main()
{
int *map;
int row, col;
printf("enter row and col value:");
scanf("%d %d", &row, &col);
map = (int *) malloc(row * col * sizeof(int));
//use the array
free(map);
return 0;
}
example function prototype:
void setMap(int *map, int row, int col);
while doing function implementation use your function prototype. just add curly brackets and start to fill in.

Resources