C pointer dereference error - c

Suppose I have the following code (example):
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void Ex(void *ret, int ret_len, int choice){
if(choice==1){
int *ret = ret;
for(int i=0; i<ret_len; i++){
*(ret+i) = i;
}
} else {
int **ret = ret;
for(int i=0; i<ret_len; i++){
for(int j=0; j<ret_len; j++){
*(*(ret+i)+j) = i*j;
}
}
}
}
int main()
{
int m[10];
Ex(m,10,1);
printf("%i",m[3]);
return 0;
}
The goal of the function is to take a pointer to preallocated memory of a one or two dimensional array.
When compiled and executed the code works when choice==1, otherwise, if I run
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void Ex(void *ret, int ret_len, int choice){
if(choice==1){
int *ret = ret;
for(int i=0; i<ret_len; i++){
*(ret+i) = i;
}
} else {
int **ret = ret;
for(int i=0; i<ret_len; i++){
for(int j=0; j<ret_len; j++){
*(*(ret+i)+j) = i*j;
}
}
}
}
int main()
{
int m[100];
Ex(m,10,2);
printf("%i", m[3][5]);
return 0;
}
no output is ever produced and the code seems to run forever (note choice is now not 1 and m is the proper size)
I am under the impression that the casting in Ex should change the shape of the array and allow main to index into it as if it were 2d but neither indexing into it as if it were 1d nor 2d work.

Having looked at the comments on the question and some answers this is what I have gathered for your requirements.
You need a generic function that takes an array of choice dimensions and initializes it with some values.
This can suit your purpose.
void Ex(void *_ret, int ret_len, int choice){
if(choice==1){
int *ret = _ret;
int i;
for(i=0; i<ret_len; i++){
ret[i] = i;
}
} else {
int (*ret)[ret_len] = _ret;
int i, j;
for(i=0; i<ret_len; i++){
for(j=0; j<ret_len; j++){
ret[i][j] = i*j;
}
}
}
}
Now this is how you can call it
int main(void) {
int first[10];
Ex(first, 10, 1);
int second[20][20];
Ex(second, 20, 2);
printf("first[4] = %d\n", first[4]);
printf("second[3][4] = %d\n", second[3][4]);
}
You can see the Demo here

because ret if of type int *, but the else part is:
for(int i=0; i<ret_len; i++){
for(int j=0; j<ret_len; j++){
*(*(ret+i)+j)=i*j;
}
}
which needs ret of type int **. and this causes the error.
The way to resolve the problem is to use void *. that is one way to use generics in C.
Take a look at qsort in C.
void Ex(void *_ret, int ret_len, int choice){
if(choice==1){
int *ret = (int *)_ret; // <---- type conversion
for(int i=0; i<ret_len; i++){
*(ret+i) = i;
}
} else {
int **ret = (int **)_ret; // <---- type conversion
for(int i=0; i<ret_len; i++){
for(int j=0; j<ret_len; j++){
*(*(ret+i)+j) = i*j;
}
}
}
}

The closest thing with least change of your existing code I came up with is:
#include <stdio.h>
void Ex(int * ret, int ret_len, int choice){
if(choice==1){
for(int i=0; i<ret_len; i++){
*(ret+i)=i;
}
}else{
for(int i=0; i<ret_len; i++){
for(int j=0; j<ret_len; j++){
*(ret + i*ret_len + j) = i*j;
}
}
}
}
int main() {
int anint[10][10];
Ex(anint, 10, 2);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {printf("%d\n", anint[i][j]);}
}
}
Basically, I mannually manipulate the offset within the Ex function. and I take the assumption that the length of the two dimensions are always the same.
A more "conventioal way" would be a true 2-dimentional array in which each element is malloc independently. Thus, the element of the first level array can be casted by force to a pointer and be dereferenced in the second level. But I am reluctant to call malloc too many times.
I hope this can solved your problem.

Related

C array vs pointer in these examples

This question doesn't require any initial explanation, other that to show the examples.
Why does this work (prints the contents of array a):
#include <stdio.h>
int a[100];
void check(int **b)
{
int i;
for (i = 0; i < 100; i++)
printf("%d ", b[0][i]);
}
int main()
{
int *arr = a;
int i;
for (i = 0; i < 100; i++)
{
a[i] = i;
}
check(&arr);
return 0;
}
and this doesn't (compiles with onlinegdb c compiler, but prints nothing)?
#include <stdio.h>
int a[100];
void check(int **c)
{
int i;
for (i = 0; i < 100; i++)
printf("%d ", c[0][i]);
}
int main()
{
int i;
for (i = 0; i < 100; i++)
{
a[i] = i;
}
check((int**)&a);
return 0;
}
I understand that array is a special data type in C, but shouldn't casting it to a pointer type or assigning it to one be the same? Is there a way to make the second example work without the additional pointer?

Change values of 2D array in function

The following code works perfectly well if I put the function content into the main block, but the function completely fails here. I currently get a 'subscripted value is neither array nor pointer nor vector' error. I also get 'passing argument 1 and 4 of 'accumulate' from incompatible pointer type' errors.
void accumulate( double sum[], int ypos[], int xpos[], int vals[], int numvals )
{
for(int i=0 ; i<numvals ; i++) /// start looping over indices
{
sum[ypos[i]][xpos[i]] += vals[i];
}
}
int main()
{
int xpos[2] = {0,1};
int ypos[2] = {0,1};
double vals[2] = {1.01,7};
int numvals = 2;
int size = 6;
double sum[size][size];
for(int i=0; i<size ;i++)
{
for(int j=0; j<size ; j++)
{
sum[i][j] = 0; // make zeros
}
}
accumulate(sum,ypos,xpos,vals,numvals); // doesn't work
for(int i=0; i<size ;i++)
{
for(int j=0; j<size ; j++)
{
printf("%f ", sum[i][j]);
}
printf("\n");
}
}
2d array when passed to function that decays into T (*)[COLS]. Or alternatively you can write
void func( int col, int arr[][col]);
So you would write
void accumulate( double sum[][size], int ypos[], int xpos[], int vals[], int numvals )
{
...
}
Also you should be aware the ypos[i] and xpos[i] should be within the limit of the array size so that you don't run into undefined behavior.

getting weird output from 2 d array in C

I want to a fill a small 2 d array with arbitrary values before moving onto a bigger array. However, when I compile and run my program, I get some weird output. It is not perfectly square. if someone could point out what im doing wrong that would be great.
void startarray(char (*arr)[10], int y_length, int x_length);
void printarray(char (*arr)[10], int y_length);
int main()
{
char arr[10][10];
startarray(arr, 10,10);
printarray(arr, 10);
return 0;
}
void startarray(char (*arr)[10], int y_length, int x_length)
{
int i;
int j;
for(i = 0; i <= y_length; i++)
{
for(j = 0; j < x_length; j++)
{
arr[i][j] = 'a';
}//end for
arr[i][j] = '\0';
}//end for
}
void printarray(char (*arr)[10], int y_length)
{
int i = 0;
while(i < y_length)
{
printf("\n%s", arr[i]);
i++;
}//end while
}

stack overflow unless printf under recursion

This code below is the code for finding the determinant for 3x3 matrix (this code is intended for nxn matrix, but for the sample, I used 3x3), using recursive
The result is working fine, but I wonder what errors in this code make this must be the printf("\n") before calling the sub-function (itself) or else it will return the error 0xc0000fd (stack overflow).
#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#define size 3
void trimarray(int**rrayrc,int**rrayout, int dim,int cuti,int cutj)
{
int i, j;
int ti = 0,tj;
for(i = 0; i<dim; i++)
{
tj = 0;
for(j = 0; j< dim; j++)
{
if(!((i==cuti)||(j==cutj)))
{
rrayout[ti][tj] = rrayrc[i][j];
}
if(j!=cutj) {tj++;}
}
if(i!=cuti) {ti++;}
}
}
void initializearray(int** rray,int dim)
{
int i, j;
for(i = 0; i<dim; i++)
{
for(j = 0; j<dim; j++)
{
rray[i][j] = 0;
}
}
}
int det(int** rray, int dim)
{
int i,j;
int cut[dim-1][dim-1];
int* cutp[i];
int mul = 1,sum=0;
if(dim >1)
{
for(i = 0; i<dim-1; i++)
{
cutp[i] = cut[i];
}
initializearray(cutp,dim-1);
for(i = 0; i<dim; i++)
{
printf("\n",dim); //<< Without this the program won't work
trimarray(rray,cutp,dim,0,i);
sum+=det(cutp,dim-1)*mul*rray[0][i];
mul = 0-mul;
}
return sum;
}
else
{
return rray[0][0];
}
}
int main()
{
int test[size][size] = {2,-3,-2,-6,3,3,-2,-3,-2};
int* testpntr[size];
int i,deter;
for(i = 0; i<size; i++)
{
testpntr[i] = test[i];
}
deter = det(testpntr,size);
printf("[%d]",deter);
getch();
return 0;
}
The answers will be dearly appreciated.
int* cutp[i]; is undefined behavior since i is uninitialized at this stage. You have no idea what is the size of cutp array.

4-dimensional array allocation: access violation

I wrote this simple piece of code to dynamically allocate a 4-dimensional array:
#include <stdlib.h>
#include <stdio.h>
int**** alloc() {
int i,j,k;
int ****matrix;
int x,y,z,n_pairs;
x= 62;
y= 45;
z= 28;
n_pairs = 4;
matrix = (int ****) malloc(x*sizeof(int***));
for (i=0; i<x; i++) {
matrix[i] = (int ***) malloc(y*sizeof(int**));
if(matrix[i]==NULL)
return NULL;
for (j=0; j<y; j++) {
matrix[i][j] = (int **) malloc(z*sizeof(int*));
if (matrix[i][j] == NULL)
return NULL;
for (k=0; k<n_pairs; k++) {
matrix[i][j][k] = (int *)calloc(n_pairs,sizeof(int));
if (matrix[i][j][k] == NULL)
return NULL;
}
}
}
return matrix;
}
void freeMatrix(int ****m) {
int i,j,k;
int x,y,z;
x= 62;
y= 45;
z= 28;
for(i=0; i<x; i++) {
for(j=0; j<y; j++) {
for(k=0; k<z; k++)
free(m[i][j][k]);
free(m[i][j]);
}
free(m[i]);
}
free(m);
}
int main() {
int i,j,k,h;
int ****m = NULL;
m = alloc();
for(i=0;i<62;i++)
for(j=0;j<45;j++)
for(k=0;k<28;k++)
for(h=0;h<4;h++)
printf("%d\t",m[i][j][k][h]);
system("pause");
return 0;
}
the problem is that I this code results in an Access Violation when I try to execute it.
Isn't it the correct way to allocate/free a multidimensional array? If yes, then what is the problem?
One problem is here:
for (k=0; k<n_pairs; k++) { //<----- This should read `k<z'
matrix[i][j][k] = (int *)calloc(n_pairs,sizeof(int));
You probably meant to loop to z, not to n_pairs.
if u make a matrix the correct way is to allocate all the memory u need, then dived it up.
for 2.dim
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int i;
int ** matrix;
int rows = 10;
int colums =10;
matrix = (int**)malloc(rows*sizeof(int*));
matrix[0] = (int*)malloc(rows*colums*sizeof(int));
for(i =1; i<rows;i++)
matrix[i] = &matrix[i-1][colums];
free(matrix[0]);
free(matrix);
return 0;
}
this is for having a continues memory area for the matrix. this can be faster

Resources