How to send array as pointer to function C - 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.

Related

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 pass and return two-dimensional array from function in c

I am relatively new to c, and I still have not been able to find a good way of passing and returning a multi-dimensional array from a function. I found the following code, however it doesn't seem like a good way to do things because it passes the array and then to use it, it creates a duplicate with the malloc function. Is there a way to do it without the copying and malloc function, or a better way to pass and return an 2d array from a function in c in general? Thanks.
#include <stdio.h>
#include <stdlib.h>
int **matrix_sum(int matrix1[][3], int matrix2[][3]){
int i, j;
int **matrix3;
matrix3 = malloc(sizeof(int*) * 3);
for(i = 0; i < 3; i++) {
matrix3[i] = malloc(sizeof(int*) * 3);
}
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
matrix3[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
return matrix3;
}
int main(){
int x[3][3], y[3][3];
int **a;
int i,j;
printf("Enter the matrix1: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&x[i][j]);
}
}
printf("Enter the matrix2: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&y[i][j]);
}
}
a = matrix_sum(x,y); //asigning
printf("The sum of the matrix is: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%d",a[i][j]);
printf("\t");
}
printf("\n");
}
//free the memory
for(i = 0; i < 3; i++) {
free(a[i]);
}
free(a);
return 0;
}
The array are not copied for agurments. Just pointers to the first elements of them (int[3]) are passed.
To avoid malloc(), you should add another argument to specify the array where the result should be stored.
#include <stdio.h>
void matrix_sum(int matrix3[][3], int matrix1[][3], int matrix2[][3]){
int i, j;
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
matrix3[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
}
int main(){
int x[3][3], y[3][3], a[3][3];
int i,j;
printf("Enter the matrix1: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&x[i][j]);
}
}
printf("Enter the matrix2: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
scanf("%d",&y[i][j]);
}
}
matrix_sum(a,x,y);
printf("The sum of the matrix is: \n");
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
printf("%d",a[i][j]);
printf("\t");
}
printf("\n");
}
return 0;
}
An array can be declared and used through a reference (pointer)
for instance
char array[] = {'h','e','l', 'l', 'o', '\0'};
char *pointer = array;
the way pointers work can be understood by calling sizeof() on a given type
printf("char:%d\nchar_pointer: %d\n", sizeof(char), sizeof(char*));
which results in the following output.
char:1
char_pointer: 4
these results mean that even though a char has 1byte, its pointer needs 4 in order to be stored in memory thus, they are not the same type.
now in order to pass an array as an argument to a function you have many options
void function1(array[4])
{
//this function can receive an array of four elements and only four elements;
//these types of functions are useful if the algorithm inside the function only works
//with a given size. e.g. matrix multiplication
}
//or
void function2(char array[], int size)
{
//this function can receive an array of elements of unknown size, but you can
//circumvent this by also giving the second argument, the size.
int i;
for(i = 0; i <= size; i++)
{
printf("%c", array[i]);
}
}
In order to use or call any of these functions you could pass the array or a pointer to the array
function2(array, 5);
function2(pointer, 5);
//these results are the same
The same applies to a multidimensional array
void function3(char** multi_dim_array, array_size_first_dim, array_size_second_dim);
//and you can call it by using the same syntax as before;
void main(int argc, char[] argv*)
{
char** multi_dim = malloc(sizeof(char*) * 3);
int i;
for(i = 0; i<=3 ; i++)
{
multi_dim[i] = malloc(sizeof(char) * 4);
}
function3(multi_dim, 3,4);
}
if you want to return a multidimensional array you can just return a pointer
char **malloc_2d_array(int dim1, int dim2)
{
char ** array = malloc(sizeof(char*)*dim1);
int i;
for(i = 0; i<=dim2; i++)
{
array[i] = malloc(sizeof(char) * dim2);
}
return array;
}
as a final note, the reason the code you found, copies the array, is because of functional programming(a way of programming if you will) where a function call cant modify its input, thus it will always create a new value;
First of all this is not gonna be a technical explanation. I am just gonna try and explain what works not why.
For passing a multidimensional array you can use either an array with a defined size as you did in your example code:
void matrix_sum(int matrix3[][3])
Or if you don't want to use a defined size and want to take care of memory usage you can use a pointer to a pointer. For this case you also need to pass the size (unless you are passing NULL-terminated strings). Like this:
void matrix_sum(int **matrix, int size)
BUT for this case you can't call the function with a "normal" array. You need to use a pointer to a pointer or a pointer to an array.
int **matrix;
// make sure to allocate enough memory for this before initializing.
or:
int *matrix[];
For returning an array you can just return a pointer to a pointer like you did in your code example.
But you don't need to return an array, because if you change a value in an array, (in a different function) the value will stay changed in every other function.
A short example for this:
#include <stdio.h>
void put_zeros(int matrix[][3])
{
int i;
int j;
i = 0;
while (i < 3)
{
j = 0;
while (j < 3)
{
matrix[i][j] = 0;
j++;
}
i++;
}
}
void print_matrix(int matrix[][3])
{
int i;
int j;
i = 0;
while (i < 3)
{
j = 0;
while (j < 3)
{
printf("%d ", matrix[i][j]);
j++;
}
printf("\n");
i++;
}
}
int main(void)
{
int matrix_first[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
print_matrix(matrix_first);
put_zeros(matrix_first);
print_matrix(matrix_first);
}
This will print "1 2 3 4 5 6 7 8 9" because that's the first value we assigned.
After calling put_zeros it will contain and print "0 0 0 0 0 0 0 0 0" without the put_zeros returning the array.
1 2 3
4 5 6
7 8 9
0 0 0
0 0 0
0 0 0

C pointer to 2d array

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 );

How to use second rank pointer rightly?

I have a 2D array called matrix, now I would like to add one to every element.
#include <stdio.h>
#include <stdlib.h>
int **add_one(int **matrix, int m, int n) {
int i, j;
int **new_mat;
new_mat = (int **) malloc(m * n *sizeof(int));
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
new_mat[i][j] = matrix[i][j] + 1;
}
}
//return the 2nd rank pointer
return new_mat;
}
int main() {
int matrix[3][2] = {1, 2, 3, 4, 5, 6};
int **new_mat;
int i, j;
new_mat = add_one(matrix, 3, 2);
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
printf("%d ", new_mat[i][j]);
}
printf("\n");
}
free(new_mat);
}
However, the compiler told me that
[Error] cannot convert 'int (*)[2]' to 'int**' for argument '1' to 'int** add_one(int**, int, int)'
It works a bit differently from what you thought
#include <stdio.h>
#include <stdlib.h>
// you can only pass what you have
int **add_one(int matrix[3][2], int m, int n)
{
int i, j;
int **new_mat;
// allocate m pointers (the rows)
new_mat = malloc(m * sizeof(*new_mat));
for (i = 0; i < m; i++) {
// allocate space for n ints
new_mat[i] = malloc(n * sizeof(int));
for (j = 0; j < n; j++) {
new_mat[i][j] = matrix[i][j] + 1;
}
}
//return the 2nd rank pointer
return new_mat;
}
int main()
{
// you forgot to encapsulate the rows, too
int matrix[3][2] = { {1, 2}, {3, 4}, {5, 6} };
int **new_mat;
int i, j;
new_mat = add_one(matrix, 3, 2);
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
printf(" %d ", new_mat[i][j]);
}
printf("\n");
}
free(new_mat);
}
If you want to pass the two-star matrix as a two-star matrix you need to build it like the new_mat in the function add_one.

receive 2d pointer array in the calling function

I am trying to receive a 2D pointer array in the calling function.
I called a function subsets from the main function, the subset function will be returning a 2D pointer array
int **subsets(int *A, int n1, int *len1)
{
int **arr;
num = pow(2, n1);
*len1 = num;
arr = (int **) malloc(num * sizeof(int *));
for (i = 0; i < num; i++)
{
arr[i] = (int *)malloc(sizeof(int));
}
return arr;
}
In this function I am declaring a 2D array dynamically int **arr and then trying to receive this return array in the main function. Note than in *len1 I am assigning the rows value the 2D array and the column values of the 2D array will be different bases on the subsets, like for a given array[1,2,3] it will be like this:
[
[],
[1],
[1, 2],
[1, 2, 3],
[1, 3],
[2],
[2, 3],
[3],
]
I am basically doing the subset problem, but not able to receive the 2D return array in the main function, can somebody please tell me how to receive this 2D pointer array in a calling function.
Appreciate the response..:)
[update from comment:]
This is how I tried to call to it from main function, but it's wrong:
int **res = subsets(A, n1, &len1);
int i = 0, j = 0;
for(i = 0; i < len1; i++)
{
for(j = 0; j < n1; j++)
{
printf("%d", res[i][j]);
}
printf("\n");
}
As n1 (column) value will be different for each row.
I'm not quite sure what you want to achieve, but I suppose the following code may help you:
#include <stdio.h>
#include <stdlib.h>
int **subsets(int A);
int main(void)
{
int **arr = subsets(3);
int i, j;
for(i = 0; i < 1 << 3; i++)
{
for(j = 0; arr[i][j]; j++)
{
printf("%d", arr[i][j]);
}
putchar('\n');
}
}
int **subsets(int A)
{
int **arr = malloc(sizeof (int *) * (1 << A));
int i;
for(i = 0; i < 1 << A; i++)
{
arr[i] = malloc(sizeof (int) * A); // Can be smaller
int *ptr = arr[i];
int j;
for(j = 0; j < A; j++)
{
if(i & (1 << j))
{
*ptr++ = j + 1;
}
}
*ptr = 0;
}
return arr;
}
Purely for brevity, things like checking the return value of malloc() are omitted. Don't forget to add them.

Resources