Passing an array to a function changes its values? - c

The intended result is the printing of the same values that we input, but the output is zero after the first row.
#include<stdio.h>
void display(int *q, int);
int main() {
int i,j,n;
int d[50][50];
printf("Input the order\t");
scanf("%d", &n);
for (i=0;i<=(n-1);i++) {
for (j=0;j<=(n-1);j++) {
scanf("%d", &d[i][j]);
}
}
display (d, n);
}
void display (int *q, int r) {
int i,j;
for (i=0;i<r;i++) {
for (j=0;j<r;j++) {
printf("%d\t", *(q + i*r + j));
}
printf("\n");
}
}

Your function is declared with a parameter of type int *. You are attempting to pass an argument of type int [50][50], which decays to pointer type int (*)[50]. These pointer types are incompatible. Language does not support implicit conversion from int (*)[50] to int. Your code is not a valid C program, and I'm sure your compiler told you about it.
A more meaningful thing to do would be to declare your function as
void display (int n, int q[n][n])
and access your array elements in a natural way as
q[i][j]
However, for that you will have to use true array sizes as n (i.e. 50 in your case). If you want to process a smaller sub-matrix of elements, you will have to pass its size separately.
But if you really want to use your "hack", you will have to use an explicit cast when calling your function
display ((int *) d, n);
and keep in mind that each row of your original array still contains 50 elements, as declared, regardless of the value of n. This means that inside your function you will have to use 50 as row size multiplier
void display (int *q, int r) {
int i,j;
for (i=0;i<r;i++) {
for (j=0;j<r;j++) {
printf("%d\t", *(q + i*50 + j));
}
printf("\n");
}
}

your display routine assumes that the 2D array is [n][n] whereas it is [50][50].
You have to pass the actual 2D array dimension alongside with n, the display routine cannot know the actual 2D array size.
You could declare your array dynamically like this:
printf("Input the order\t");
scanf("%d", &n);
int d[n][n];
and then avoid the warning
test.c:20:18: warning: passing argument 1 of 'display' from incompatible pointer type
display (d, n);
here by casting explicitly to 1D pointer (since you know the structure):
display ((int*)d, n);

Related

c Functions with arrays

Is it possible to make a function that works with arrays of undefined length?
For example, I made this code to fill a matrix of 3x3 and I wonder if is there a way to do this but with a matrix of nxn.
void fillMatrix(double mat[][COLS])
{
int i,j;
printf("Enter the %d matrix elements:\n",COLS*ROWS);
for(i=0;i<ROWS;i++)
{
for(j=0;j<COLS;j++)
{
scanf("%lf",&mat[i][j]);
}
}
printf("\n");
}
In this code I defined ROWS=COLS=3.
Yes, if you know the number of columns in the 2D array at the time of passing it to the function. You do not have to define COL beforehand.
void foo(int col, int arr[][col]) {
//Do something
}
You can try this:
void func(void *data, int row, int col)
{
int (*a)[col] = (int(*)[col])data;
//now you can access a[i][j] with i<row and j<col
//data must be an continous array
//replace int with your data type
}
Working code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n = 5;
int (*a)[n];
int b[5][5];
a = (int(*)[n])b;
b[0][0]=0;
b[0][1]=1;
b[2][1]=111;
b[1][2]=666;
b[4][3]=222;
printf("%d\n", a[0][0]);
printf("%d\n", a[0][1]);
printf("%d\n", a[2][1]);
printf("%d\n", a[1][2]);
printf("%d\n", a[4][3]);
return 0;
}
may be you can add a new parameter row to your function fillMatrix(double mat[][COLS]), that is, fillMatrix(double mat[][col], int row)
another way:
double** matrix = (double**) malloc(sizeof(double*)*n);
for(int i = 0; i<n; i++){
matrix[i] = (double*) malloc(sizeof(double)*n);
}
then change the function to: fillMatrix(double** matrix, int n)
Is it possible to make a function that works with arrays of undefined length?
You'll better know the dimension of the array. If it is a function argument, you should in general pass the dimension in some other argument.
Remember that when passed as argument, an array is decayed into a pointer. Look also into some C reference site and later refer to the C11 standard n1570.
In your case, you want to define then have an abstract data type (probably some opaque pointer) for your matrixes. Using flexible array members could be useful. See this answer for details.
yes, you can do it using dinamic memory.
you will something like:
void fillMatrix(double** mat, int rows, int cols) {
int i,j;
printf("Enter the %d matrix elements:\n",rows*cols);
for(i=0;i<rows;i++)
{
for(j=0;j<cols;j++)
{
scanf("%lf",&mat[i][j]);
}
}
printf("\n");
}
where double** mat is a vector of vectors that you will have to ask for memory using malloc for the rows and the malloc for the columns.

Passing array to function by value or reference the same?

I want to know if there is any real difference; I have written code that as it feel it a passing by copy not reference but it acts as reference.
Here is the code:
#include <stdio.h>
#include <conio.h>
using namespace std;
int pause = 0;
void display(int b[5], int size){
for (int i = 0; i < size; i++){
printf("\n%d",b[i]," at:");
printf(" %d", &b[i]);
}
}
void main(){
int num[] = { 2, 4, 6, 8, 10 };
printf("\nIn main function.");
for (int i = 0; i < 5; i++){
printf("\n%d", num[i], " at:");
printf(" %d", &num[i]);
}
display(num,5);
scanf("%d", pause);
}
You cannot pass an array itself to a function at all, nor can you return one. In particular, despite the appearance of its declaration, your function display() does not receive an array as a parameter. It's declaration is 100% equivalent to this one:
void display(int *b, int size);
and this one:
void display(int b[], int size);
Expressions of array type are automatically converted to pointers in almost every context in which they can appear, so this function call:
display(num,5);
is equivalent to
display(&num[0],5);
Nevertheless, there is a potential difference to call out in this area: the expression &num is not equivalent to &num[0]. They refer to the same address, but the two expressions have different types. Passing the former would be the analog of passing the array by reference, but that expression does not have the correct type for the first argument to your display() function. A function that wants to receive &num needs to be declared differently:
void display2(int (*b)[5]);
or
void display3(int n, int (*b)[n]);
The latter requires C99, or C2011 with VLA support (which is required in C99, but optional in C2011).

Error while running code - makes pointer from integer without a cast

I'm trying to run my code but I get 5 errors and they're all of the same kind.
The first is:
note: expected 'int (*)[3]' but argument is of type 'int'
In, for example, this part of my code (it points out on the line where you see the word HERE
HERE-> int isNeighbourClose(int mat[N][M], int i, int j, int a, int b){
int m;
m=calcDistance(mat[i][j], mat[a][b]);
if(m<=1)
{
return 1;
}
return 0;
}
And the other is:
error: passing argument 1 of 'isNeighbourClose' makes pointer from integer without a cast
In, for example, this part of my code
int isCellExtreme(int mat[N][M], int i, int j){
int a, b;
int m;
for(a=-1;a<=1;a++)
{
if((i+a>=0) && (i+a<=N))
{
for(b=-1;b<=1;b++)
{
if((j+b>=0) && (j+b<=M))
{
if((a!=0)||(b!=0))
{
HERE-> m=isNeighbourClose(mat[N][M], i, j, i+a, j+b);
if(m)
{
return 0;
}
}
}
}
}
}
return 1;
}
I went over this a couple of times and can't find where the problem is. Any idea where I'm mistaken?
Thanks in advance.
When you pass mat[N][M] to isNeighbourClose, you're not passing a 2D array like you think you are. You're passing in the single element of mat at row N column M.
The function expects a 2D array, so pass the whole array:
m=isNeighbourClose(mat, i, j, i+a, j+b);
EDIT:
When you have a declaration like this:
int mat[N][M];
You're specifying the datatype and (in this case) the dimensions of the array, i.e. it says "mat is an array of N by M elements". This differs from an expression as mentioned above where mat is being used.

warning passing argument 1 of " " from incompatible pointer type enabled by default

randomAssign(int **grid, int size){
int m = rand()%size;
int n = rand()%size;
grid[m][n] = 1;
}
int main()
{
srand(time(NULL));
int i, j, size;
scanf("%d", &size);
int grid[size][size];
for(i=0; i<size; i++){
for(j=0; j<size; j++){
grid[i][j] = 0;
}
}
randomAssign(grid,size); //warning
return 0;
}
I am getting warning when i call the function. I tried all i can do but i couldn't find the mistake. Where is the mistake? Regards...
Arrays and pointers are different. An array is a series of contiguous elements of a particular type. A pointer is a small object that holds the address of another object.
Your function expects a pointer that points to another pointer. However you tried to supply an array to it. This can't possibly work.
One way to fix your code would be to make the function accept a pointer to an array (not a pointer to a pointer). This could be written:
void randomAssign(int size, int grid[size][size])
This is actually the same as having int (*grid)[size], the first size is redundant (see here for detail) however it serves some documentary purpose.

incompatible with parameter of type "int *"

This is my final version for gameoflife. I have this error bug I can't fix. Please help me to solve this one:
1 IntelliSense: argument of type "int (*)[50]" is incompatible with parameter of type "int *"
line 79 print(board, HEIGHT, WIDTH);
void print(int *board, int rows, int cols)
{
int x, y;
char c;
for (y = 0; y < rows; y++) {
for (x = 0; x < cols; x++) {
if (*(board + y*cols + x) == 1)
printf("X");
else
printf(" ");
}
printf("\n");
}
printf("Press any key to continue:\n");
getchar();
}
That error means you are trying to pass a function an argument of type "array of 50 pointers to int" while it should be getting an argument of type "pointer to int" (which could also be an array).
In your case, the signature of your print() function should probably change to get an int board[][WIDTH] instead of int * which it gets now.
The change of the signature also requires a change in the function code, so the line
if (*(board + y*cols + x) == 1)
Should be changed to:
if (board[y][x] == 1)
void print(int *board, int rows, int cols)
...
int board[HEIGHT][WIDTH];
...
print(board, HEIGHT, WIDTH);
Your print function first parameter is of type int *board but you are calling the function with an argument of type int (*)[50].
You should fix your print function prototype (and body) to work with a parameter of the right type (i.e., int (*)[50]).
you declare
void print(int *board, int rows, int cols)
but in the the other functions you have used
foo(int board[][WIDTH], int rows)
either keep same or declare as
(int **board, int rows, int cols )
Your print function is expecting a pointer to int, but you are passing a 2-dimensional array, which decays to a pointer to a 1-dimensional array. Either cast board to an int* or convert print() to handle a 2-d array.
Casting the call would look something like this:
print((int *)board, HEIGHT, WIDTH);
Converting print() to take a 2D array as argument would look something like this:
void print(int board[][WIDTH])
{
int x, y;
char c;
for (y = 0; y < HEIGHT; y++) {
for (x = 0; x < WIDTH; x++) {
if (board[y][x] == 1)
printf("X");
else
printf(" ");
}
printf("\n");
}
printf("Press any key to continue:\n");
getchar();
}
why don't you just do like what sverre told you to, since a multidimensional array is really an abstraction the compiler provides not to do the maths you did to find the row_th and col_th element
just call it like print((int *)board, HEIGHT, WIDTH);
Your board is a double array. It has both height and width. When you expect a *board argument in your print you actually expect an array with only one dimension. For the error to go away you have to pass int (*board)[WIDTH].
When you pass a two-dimensional array to a function you have to include the size of one of the dimensions. So your board[HEIGHT][WIDTH] has to be passed with, at least, the information about it's width. So : board[][WIDTH]. You can take those empty [] and write them down as a pointer in front of board.
So, in your main you call your function correctly, but you have to edit your function's head to be like :
void print(int (*board)[WIDTH], int rows, int cols){

Resources