C pointer to 2d array - c

So i'm creating a loop which can create a 3x3 board by setting the elements of a [3][3] array to enum EMPTY. While debugging, I can see that the program sets the first three elements of the array correctly before getting a memory access violation error, so I know this is a problem with the address of the second row of the array (when the 'i' variable turns from 0 to 1). How do I solve this? pointers are still a bit confusing to me tbh.
int main(void)
{
int board[3][3] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int* p = &board;
create_board(p);
print_board(p);
return 0;
}
void create_board(int *board)
{
for (int i = 0; i < 3; ++i)
{
for (int k = 0; k < 3; ++k)
{
(&board)[i][k] = EMPTY;
}
}
return;
}

Your code has many issues. Arrays in C do not hold any information about their sizes.
The easiest way is to use a pointer to the array:
void create_board(size_t rows, size_t cols, int (*board)[rows])
{
for (size_t i = 0; i < rows; ++i)
{
for (size_t k = 0; k < cols; ++k)
{
board[i][k] = EMPTY;
}
}
}
and main
int main(void)
{
int board[3][3];
create_board(3,3, board);
print_board(3,3,board);
return 0;
}
Similar way you can write print_board function:
void print_board(size_t rows, size_t cols, int (*board)[rows])
{
for (size_t i = 0; i < rows; ++i)
{
for (size_t k = 0; k < cols; ++k)
{
printf("[%zu][%zu] = %d\t", i, k, board[i][k]);
}
printf("\n");
}
}

Your code is invalid. The compiler should issue a message that there are used incompatible pointer types in this declaration
int* p = &board;
The initializing expression has the type int ( * )[3][3] while the initialized object has the type int *.
The function can be declared either like
void create_board( int ( *board )[3], size_t n )
{
for (size_t i = 0; i < n; ++i)
{
for (size_t k = 0; k < 3; ++k)
{
board[i][k] = EMPTY;
}
}
}
and called like
int ( *p )[3] = board;
create_board( p, 3 );
Or if your compiler supports variable length arrays then like
void create_board( size_t m, size_t n, int ( *board )[n] )
{
for (size_t i = 0; i < m; ++i)
{
for (size_t k = 0; k < n; ++k)
{
board[i][k] = EMPTY;
}
}
}
and called like
int ( *p )[3] = board;
create_board( 3, 3, p );

Related

Returning New Array and getting wrong output

#define N 3
int subMatrix(int a[][N]) {
int i, j;
int sum = 0;
int arr[N];
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
sum += a[i][j];
sum -= a[j][i];
}
arr[i] = sum;
sum = 0;
}
return *arr;
}
void main() {
int a[N][N] = {
{9,2,4},
{3,7,11},
{3,1,2}
};
for (int i = 0; i < N; i++) {
printf("%5d", subMatrix(a[i]));
}
}
The function works fine, the problem is when I'm returning the new array and loop over it in the main function I get the first element of the array and the other elements are addresses.
i did it before with another array with size of doubles and it worked.
There is something i miss?
double avgMatrix(int a[][C]) {
int i, j, sum=0;
double M[R];
for (i = 0; i < R; i++) {
for (j = 0; j < C; j++) {
sum += a[i][j];
}
M[i] = (double)sum / C;
sum = 0;
}
return *M;
}
void main() {
int a[R][C] = {
{9,2,4},
{3,8,11},
{3,1,2}
};
for (int i = 0; i < R; i++)
printf("%5.2lf", avgMatrix(a[i]));
}
this code works. what can be the difference?
I do not really understand what your function subMatrix does.
Your code needs a few modifications to be able to compile.
First, include the necessary header #include <stdio.h>, because your code needs printf.
Second, make sure the passed parameter and the attribute be the same type.
Third, if you would like to return an array from a function, you should use dynamic allocation function to help you do that. malloc
/* At least, make sure to include necessary head files
* #include <stdio.h>
*/
#define N 3
int subMatrix(int a[][N]) {
int i, j;
int sum = 0;
int arr[N];
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
/* Because the passed parameter is one dimensional
* so the following code does not make sense.
*/
sum += a[i][j];
sum -= a[j][i];
}
arr[i] = sum;
sum = 0;
}
/* arr is a local variable. It is actually a pointer
* It should never be returned.
* In fact, *arr is only the first element of the array of arr.
* At least, you should return the address of the first element.
* Considering your purpose, to use dynamic allocation is proper.
*/
return *arr;
}
/* 'void main()' is not right.
* 'int main(void)' is the right way.
*/
void main() {
int a[N][N] = {
{9,2,4},
{3,7,11},
{3,1,2}
};
for (int i = 0; i < N; i++) {
/* a[i] is a one-dimensional array,
* but subMatrix needs a two dimensional one.
*/
printf("%5d", subMatrix(a[i]));
}
}
A possible working code:
#include <stdio.h>
#include <stdlib.h>
#define N 3
int *subMatrix(int a[N][N]) {
int sum = 0;
int *arr = (int *)malloc(N*sizeof(int));
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
sum += a[i][j];
sum -= a[j][i];
}
arr[i] = sum;
sum = 0;
}
return arr;
}
int main(void) {
int a[N][N] = {
{9,2,4},
{3,7,11},
{3,1,2}
};
int *arr = subMatrix(a);
for (int i = 0; i < N; i++)
printf("arr[%d] : %d\n", i, arr[i]);
free(arr);
}
Is this what you want? Try it.

Return an Array from a function C: Subscripted value is not an array, pointer, or vector

I need to return the value of the matrix, but I am gettin this error
Subscripted value is not an array, pointer, or vector
in:
qk_output[m][o] = 0;
and
qk_output[m][o] += queries[m][n] * keys[n][o];
Could anyone help me? Thanks!
int* multmm(int queries[M][N], int keys[N][O]) {
// Matrix Multiplication
int* qk_output = (int*)malloc(sizeof(int) *M*N);
for (int m = 0; m < M; m++) {
for (int o = 0; o < O; o ++) {
qk_output[m][o] = 0;
for (int n = 0; n < N; n++) {
qk_output[m][o] += queries[m][n] * keys[n][o];
}
}
}
return qk_output;
}
To return a 2D array from a function, you can do
#define N 4
#define M 3
int (*foo(void ))[N]
{
int (*p)[N] = malloc(M * sizeof *p);
for (int i = 0; i < M; ++i)
{
for (int j = 0; j < N; ++j)
{
p[i][j] = i + j;
}
}
return p;
}
int main (void){
int (*mat)[N] = foo();
for (int i = 0; i < M; ++i)
{
for (int j = 0; j < N; ++j)
{
printf("%d ", mat[i][j]);
}
puts("");
}
free(mat);
return 0;
}
int* qk_output = (int*)malloc(sizeof(int) *M*N);
qk_output is a pointer to an int
the compiler knows how to access qk_output[n] but doesn't know how to access qk_output[m][n], you need to switch to:
int (*qk_output)[N] = malloc(sizeof(*qk_output) * M); // Don't cast malloc
that is, a pointer to an array of N ints
Now the compiler has enough information to access qk_output[m][n]
For the return question: you can use void *multmm(...) or int (*multmm(...))[N], the second one gives more information to the compiler so it is less error prone.
Something like:
int (*multmm(int queries[M][N], int keys[N][O]))[N]
{
int (*qk_output)[N] = malloc(sizeof(*qk_output) * M);
...
return qk_output;
}
int main(void)
{
int (*arr2D)[N] = multmm(...);
...
}

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.

How to make a function returning a dynamically-allocated two-dimensional array?

I am trying to return a contiguous memory allocated array from a function but I keep on receiving errors.
Compiler returns a warning saying return from incompatible pointer type [-Wincompatible-pointer-types]
Can someone tell me what I am doing wrong?
int *test() {
size_t rows, cols;
// assign rows and cols
rows = 3;
cols = 3;
int count = 0;
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr) {
// do stuff with arr[i][j]
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; j++) {
arr[i][j] = count;
count++;
}
/* code */
}
}
return arr;
}
int main() {
size_t rows, cols;
// assign rows and cols
rows = 3;
cols = 3;
int count = 0;
int (*arr)[cols] = malloc(sizeof *arr * rows);
arr = test();
int i = 0;
int j = 0;
for (i = 0; i < rows; ++i) {
for (j = 0; j < 3; ++j)
printf("%d ", arr[i][j]);
printf("\n");
}
free(arr);
}
it should return a 2D array but returns an error and am using gcc on ubuntu
Your allocation function is fine, except for a few details:
you should pass rows and cols as arguments
you should use type size_t for i and j and iterate to rows and cols instead of hard coded bounds.
you should use parentheses in malloc(sizeof *arr * rows); for readability:
malloc(sizeof(*arr) * rows);
you should return &arr[0][0] or arr[0] for type correctness.
The problem is you cannot define the return type of test to be pointer to 2D array of a parametric second dimension. Hence the type error on the assignment arr = test(); cannot be fixed. You can work around this shortcoming by casting the return value to (int (*)[cols]) or simply (void *).
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int *test(size_t rows, size_t cols) {
int (*arr)[cols] = malloc(sizeof(*arr) * rows);
if (arr) {
// initialize the matrix
size_t count = 0;
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
arr[i][j] = count;
count++;
}
/* code */
}
return &arr[0][0];
}
return NULL;
}
int main() {
// assign rows and cols
size_t rows = 3;
size_t cols = 3;
int (*arr)[cols] = (int (*)[cols])test(rows, cols);
if (arr) {
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
free(arr);
}
return 0;
}
Output:
0 1 2
3 4 5
6 7 8
If all what you need is
to return a contiguous memory allocated array from a function
You can ignore this answer.
If what you are trying to do is to model a bidimensional container (like a matrix) using a dynamically allocated contiguous block of memory, you could define a struct and pass that around:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct {
int rows, cols;
int values[]; // I'm using a Flexible Array Member here.
} iMat;
iMat *alloc_matrix(int rows, int columns)
{
assert(rows > 0 && columns > 0);
iMat *tmp = malloc(sizeof *tmp + sizeof *(tmp->values) * rows * columns);
if (tmp)
{
tmp->rows = rows;
tmp->cols = columns;
}
return tmp;
}
void fill_matrix_iota(iMat *m, int start)
{
if ( m )
for (size_t i = 0, n = m->rows * m->cols; i < n; ++i)
m->values[i] = start + i;
}
void print_matrix(iMat *m, int width)
{
if (m)
{
for (int i = 0, k = 0; i < m->rows; ++i)
{
for(int j = 0; j < m->cols; ++j, ++k)
{
printf("%*.d", width, m->values[k]);
}
putchar('\n');
}
}
}
iMat *make_transposed(iMat *m)
{
if ( !m )
return NULL;
iMat *tmp = alloc_matrix(m->cols, m->rows);
if ( tmp )
{
for (int i = 0; i < m->rows; ++i)
{
for(int j = 0; j < m->cols; ++j)
{
tmp->values[j * m->rows + i] = m->values[i * m->cols + j];
}
}
}
return tmp;
}
int main(void)
{
iMat *a = alloc_matrix(3, 4);
if (!a)
exit(EXIT_FAILURE);
fill_matrix_iota(a, 1);
print_matrix(a, 3);
iMat *b = make_transposed(a);
if (!b)
{
free(a);
exit(EXIT_FAILURE);
}
putchar('\n');
print_matrix(b, 3);
free(b);
free(a);
return EXIT_SUCCESS;
}

Reconstructing an array in c

Given a sparse vector (more 0s than other elements), make a function to split the vector up into two vectors (one containing the elements, and the other containing the position of the elements. Make another function to reconstruct the source vector from the position and value arrays (including the 0s in the original source).
So this doesn't reconstruct it properly - and I don't understand why. I tested the arrays val and pos in the main function, but they don't have the right numbers in them.
Here's what I have so far:
for the efficient representation (splitting the source vector into two parts):
void efficient( const int source[], int val[], int pos[], int size)
{
int j = 0;
for (j = 0; j < size; j++)
{
if (source[j] != 0)
{
val[j] = source[j];
pos[j] = j;
}
}
}
for the reconstruct function (m is size of source vector being reconstructed, n is size of position and value vectors):
void reconstruct( int source[], int m, const int val[], const int pos[], int n) {
int i = 0;
int j = 0;
int k = 0;
for (i = 0; i < m; i++)
source[i] = 0; // sets all elements in source array equal to 0
for (j = 0; j < n; j++){
source[pos[j]] = val[j];
}
for (k = 0; k < m; k++)
printf("%d ", source[k]);
}
and here's my main test function:
int main()
{
int i;
int size;
const int source[] = {0,0,23,0,-7,0,0,48};
int val[3] ;
int pos [3] ;
efficient(source,val,pos,8); // calls function efficient
reconstruct(source, 8, val, pos, 3); // calls function reconstruct with parameters source, source size = 8, value array, position array and size of value and position array
}
So this doesn't reconstruct it properly - and I don't understand why. I tested the arrays val and pos in the main function, but they don't have the right numbers in them.
void efficient( const int source[], int val[], int pos[], int size)
{
int j = 0;
for (j = 0; j < size; j++)
{
if (source[j] != 0)
{
val[j] = source[j]; <-- HERE
pos[j] = j;
}
}
}
You don't mean val[j]. You need a separate variable to count the number of entries in val and pos. Perhaps:
void efficient( const int source[], int val[], int pos[], int size)
{
int j, p;
for (j = 0, p = 0; j < size; j++)
{
if (source[j] != 0)
{
val[p] = source[j];
pos[p] = j;
++p;
}
}
}

Resources