Indexing 2-Dimentional Matrix (pointer style) - error: cant index - c

I have a problem with indexing a a 2D matrix declare as pointer.
Here is what I am doing
Compute(int *matrix, int rows, int cols )
{
int i, j;
for(j = 1; j < cols; j++)
{
for(i = 0; i < rows; i++)
{
matrix[j][i] = 5; //what is wrong with this line?
}
}
}
Error: subscripted value is neither array nor pointer
Any help?
thanks

For a 2D array pointer should be double pointer array (**matrix).In your code matrix is declared as a single dimension (*matrix) array in function arguments. It should be **matrix
Compute(int **matrix, int rows, int cols )
{
int i, j;
for(j = 1; j < cols; j++)
{
for(i = 0; i < rows; i++)
{
matrix[j][i] = 5;
}
}
}

Related

Trouble passing a 2d array to function after malloc

I've gotten back into C recently after a long absence, and I can't for the life of me remember how to pass a 2D matrix to a function and use it after mallocating it. I believe I've passed the pointer correctly, but I can't seem to actually access anything in the matrix and can't figure out why.
This is what I have written:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
void matrixOperation(int *arr, int m, int n)
{
printf("in matrixOperation\n ");
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d\n", *((arr+i*n) + j));
}
int main()
{
int i,j,count;
int row, col;
//------------------------------
printf("Number of rows?\n ");
scanf("%d", &row);
printf("Number of columns?\n ");
scanf("%d", &col);
//------------------------------
int* arr[row];
for (i = 0; i < row; i++)
arr[i] = (int*)malloc(col * sizeof(int));
count = 0;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
arr[i][j] = ++count;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d\n",arr[i][j]);
// We can also use "print(&arr[0][0], m, n);"
matrixOperation((int *)arr, row, col);
for (int i = 0; i < row; i++)
free(arr[i]);
return 0;
}
The goal was to have it accept user input for the size of the matrix, fill each index with a count and then pass it to a function which would print it out. However when I try it the print statement just outputs random numbers which I assume are what the pointers are pointing at.
I would like matrixOperation to print out the same thing as the print statement in main and I can't quite figure out what I've done wrong.
Change the function signature and you should be able to use the same piece of code.
void matrixOperation(int **arr, int m, int n)
{
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d\n",arr[i][j]);
}
Call with:
matrixOperation(arr, row, col);
Remember when an array is passed to a function, it "decays" into a pointer. You have an array of pointers. That decays to a pointer to pointers.
You declared an array of pointers:
int* arr[row];
So pass this array to the function.
The function will be declared like:
void matrixOperation(int **arr, int m, int n)
{
printf("in matrixOperation\n ");
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d\n", *( *( arr + i ) + j ) );
}
and call the function like:
matrixOperation( arr, row, col );
Though it will be better to define the function like:
void matrixOperation(int **arr, int m, int n)
{
printf("in matrixOperation\n ");
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < n; j++ )
{
printf("%d ", *( *( arr + i ) + j ) );
}
putchar( '\n' );
}
}
Pay attention to that this expression with the pointer arithmetic:
*( *( arr + i ) + j )
can be rewritten using the subscript operator the following way:
arr[i][j]
The both expressions are equivalent each other.
As for your call of the function with casting the array designator:
matrixOperation((int *)arr, row, col);
then it is wrong because you do not have one extent of memory. You allocated several extents of memory.

What actually happens when you pass a 2d array to a function in c under the hood? Does it use pointers?

You can't pass arrays by value in c, so pointers must be used? Here is the code:
#include <stdio.h>
#define N 5
void printArray(int array[N][N]) {
for(int i = 0;i < N;i++) {
for(int j = 0;j < N;j++) {
printf("%d", &array[i][j]);
}
}
}
int main() {
int array[N][N];
for(int i = 0;i < N;i++) {
for(int j = 0;j < N;j++) {
array[i][j] = 8;
}
}
printArray(array);
return 0;
}
What actually happens when the program is compiled?
Is it the same as doing this?
#include <stdio.h>
define N 5
void printArray(int* array, int rows, int cols) {
for(int i = 0;i < rows;i++) {
for(int j = 0;j < cols;j++) {
printf("%d", &array[i * cols + j]);
}
}
}
int main() {
int array[N][N];
for(int i = 0;i < N;i++) {
for(int j = 0;j < N;j++) {
array[i][j] = 8;
}
}
printArray(&array[0][0], N, N);
return 0;
}
If an array is declared to be a parameter to a function, it is adjusted to be a pointer to an element of the array.
In the case of int array[N][N], you have an array of size N, and each element of that array is an array of size N of int. This means a 2D array decays to a pointer to a 1D array.
So this:
void printArray(int array[N][N]) {
Is actually this:
void printArray(int (*array)[N]) {
And can be indexed the same way.

How to send array as pointer to function C

I am trying to make a code where i send an array from a function to be erased, i do not know the length of the array, since it will be declared after a variable that will be typed by the user, so im trying to send as a pointer. but i constantly get an error. the code looks like this
int apagaarray(int *array,int l,int c){
for(int i=0;i<l;i++){
for(int j=0;j<c;j++){
array[i][j]=0;
}
}
}
but it returns an error:
error: subscripted value is neither array nor pointer nor vector|
what is going on ? is there a way to send an array to a function without having the parameters ?
i think it would be the most correct this way:
int func(int **array, int l, int c)
{
for (int i = 0; i < l; i++) {
for (int j = 0; j < c; j++) {
array[i][j] = 0;
}
}
}
int main(void)
{
int l = 5, c = 5;
int **array = malloc(sizeof(int *) * l);
for (int i = 0; i < l; i++) {
array[i] = malloc(sizeof(int) * c);
for (int j = 0; j < c; j++) {
array[i][j] = j+1;
}
}
//print something
printf("%d\n", array[3][3]);
//empty it
// make note that im passing **array <= a ptr of ptr
func(array, l, c);
return 0;
}
not my usual self to provide a code but please try to run through it and see if that answers
Matrices should be represented as follows:
Either int **array or int *array[]
The correct function is:
int apagaarray(int **array,int l,int c){
for(int i=0;i<l;i++){
for(int j=0;j<c;j++){
array[i][j]=0;
}
}
}
#include <stdio.h>
void printArray(int *arr, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// Use address to refer the array element.
printf("%d ", *(arr + (i * cols) + j));
}
printf("\n");
}
}
void eraseArray(int *arr, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// Use address to refer the array element.
*(arr + (i * cols) + j) = 0;
}
}
}
int main()
{
int arr[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
printArray((int *)arr, 3, 3); // Cast array to 1-dim array
eraseArray((int *)arr, 3, 3); // Cast array to 1-dim array
printArray((int *)arr, 3, 3); // Cast array to 1-dim array
return 0;
}
Cast the array to one-dimensional array and pass it.
You can change the value too, Since you are passing pointers instead of values.

Getting a segmentation fault on setting value for 2d array, even though for loop counter values are inside the sizeof of array

I am declaring and printing a simple 2d array or matrix.
I am getting a segmentation fault that is being caused by the nested for loop that sets the values of the matrix.
int rows, columns;
rows = columns = 3;
int **matrix;
matrix = malloc(sizeof(int) * rows);
for (int i = 0; i < columns; i++) {
matrix[i] = malloc(sizeof(int) * columns);
}
This throws a seg fault
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
matrix[i][j] = 1;
}
}
If I set i = 1, there is no seg. fault.
for (int i = 1; i < rows; i++) {
for (int j = 0; j < columns; j++) {
matrix[i][j] = 1;
}
}
However, it does make the first 3 values printed random though.
-------
Entire Code
int main(int argc, char const *argv[]) {
int rows, columns;
rows = 3;
columns = 3;
int **matrix;
matrix = malloc(sizeof(int) * rows);
for (int i = 0; i < columns; i++) {
matrix[i] = malloc(sizeof(int) * columns);
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
matrix[i][j] = 1;
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
matrix[i][j] = 1;
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
printf("%d\n", matrix[i][j]);
}
}
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
return 1;
}
Your problem is here:
int **matrix;
matrix = malloc(sizeof(int) * rows);
You want matrix to be an array of pointers to int but you use "sizeof int" instead of "sizeof int pointer". Try:
int **matrix;
matrix = malloc(sizeof(int*) * rows);
or better
int **matrix;
matrix = malloc(rows * sizeof *matrix);
As pointed out by #n.m in a comment, the following:
for (int i = 0; i < columns; i++) {
matrix[i] = malloc(sizeof(int) * columns);
}
is wrong. It shall be:
for (int i = 0; i < rows; i++) { // Notice this change
matrix[i] = malloc(sizeof(int) * columns);
}

why does realloc throws me "Segmentation fault (core dumped)"

I am really new to C and this is for a school assignment.
So, I am tasked to transpose a given matrix.
My current function is the following:
void matrixTranspose(int rows, int cols, int **array) {
int temp[rows][cols];
int i, j;
for (i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
temp[i][j] = array[i][j];
}
}
array = realloc(array, cols * sizeof(int *));
for (i = 0; i < cols; i++) {
array[i] = realloc(array[i], rows * sizeof(int));
}
for (i = 0; i < cols; i++) {
for(j = 0; j < rows; j++) {
array[i][j] = temp[j][i];
}
}
}
If I introduce equal values for columns and rows or if the value of rows is bigger than the value of columns it works fine, but for some reason when the value of rows is smaller than the value of columns, it does not works. (Throws me "Segmentation fault (core dumped)" error).
My main looks like this:
int main() {
int **mat;
int cols, rows;
int i, j;
printf("Enter number of rows\n");
scanf("%d", &rows);
printf("Enter number of columns\n");
scanf("%d", &cols);
mat = (int **) malloc (sizeof(int *) * rows);
for (i = 0; i < rows; i++) {
mat[i] = (int *) malloc (sizeof(int) * cols);
}
for (i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
mat[i][j] = rand() % 10;
}
}
printf("\nBefore transpose: \n");
for (i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
printf("%d ", mat[i][j]);
}
printf("\n");
}
matrixTranspose(rows, cols, mat);
printf("\nAfter transpose: \n");
for (i = 0; i < cols; i++) {
for(j = 0; j < rows; j++) {
printf("%d ", mat[i][j]);
}
printf("\n");
}
}
I hope I explained myselft correctly, sorry for my english, it is not my first language. Thanks
When you modify array in matrixTranspose, you're changing a local variable. That change isn't visible in the calling function, so mat in main no longer points to valid memory.
You need to change the function to accept address of a int ** and dereference it as needed.
void matrixTranspose(int rows, int cols, int ***array) {
int temp[rows][cols];
int i, j;
for (i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
temp[i][j] = (*array)[i][j];
}
}
*array = realloc(*array, cols * sizeof(int *));
if (!*array) {
perror("realloc failed");
exit(1);
}
int min = rows < cols ? rows : cols;
for (i = 0; i < min; i++) {
(*array)[i] = realloc((*array)[i], rows * sizeof(int));
if (!(*array)[i]) {
perror("realloc failed");
exit(1);
}
}
if (rows > cols) {
for (i = min; i < rows; i++) {
free((*array)[i]);
}
} else if (cols > rows) {
for (i = min; i < cols; i++) {
(*array)[i] = malloc(rows * sizeof(int));
if (!(*array)[i]) {
perror("malloc failed");
exit(1);
}
}
}
for (i = 0; i < cols; i++) {
for(j = 0; j < rows; j++) {
(*array)[i][j] = temp[j][i];
}
}
}
Note that if the number of rows and columns are not the same, you'll need to either free the extra rows you no longer have or use malloc to allocate new rows.
Note also that you should be checking the return value of malloc and realloc for failure.
Then pass the address of mat to this function:
matrixTranspose(rows, cols, &mat);
You can change the transpose function like this:
int ** matrixTranspose(int rows, int cols, int **array) {
...
return array;
}
And then in main call it like this:
mat = matrixTranspose(rows, cols, mat);
Apart from that, I recommend these thanges. I have changed the argument to sizeof to be the actual variable instead of the type.
array = realloc(array, cols * sizeof(*array));
for (i = 0; i < cols; i++) {
array[i] = realloc(array[i], rows * sizeof(*array[0]));
}
and
mat = (int **) malloc (sizeof(*mat) * rows);
for (i = 0; i < rows; i++) {
mat[i] = (int *) malloc (sizeof(*mat[0]) * cols);
}
Your array is passed by value (i.e. you don't pass a pointer to your matrix). Yet you change it.
array = realloc(array, cols * sizeof(int *));
This is just a local change. Also,
for (i = 0; i < cols; i++) {
array[i] = realloc(array[i], rows * sizeof(int));
}
If rows < col this piece of code will try to reallocate memory for array[i] where i>rows-1. That implies deallocating the memory pointed to by array[i] has never been allocated and you have no idea where it points to.
I am tasked to transpose a given matrix.
Key problem: Code passed the pointer by value and matrixTranspose() need to receive its address in order to modify it. Well answered by others without changing much.
Yet consider a larger change instead. Do not modify the original matrix, make a transposed copy and free matrix helper functions.
int **matrixTranspose_copy(int rows, int cols, const int **array) {
int **transpose = malloc(sizeof *transpose * cols);
for (int r = 0; r < cols; r++) {
transpose[r] = malloc(sizeof *transpose[r] * rows);
for(int c = 0; c < rows; c++) {
transpose[r][c] = array[c][r];
}
}
}
return transpose;
}
void matrixFree(int rows, const int **array) {
for (int r = 0; r < rows; r++) {
free(array[r]);
}
free(array);
}
void matrixTranspose_inplace(int rows, int cols, int ***array) {
int **original = *array;
*array = matrixTranspose_copy(rows, cols, original);
matrixFree(original);
}

Resources