passing 2d arrays from one function to another in c? - c

I am trying to make a grid of blank spaces with 'x' dotted around randomly. I have managed to do this but now I want a separate function to print out the 2d array but am finding it hard to do so... any help will be great, thanks in advance.
int* createEnvironment(int width, int height, int numOfX)
{
int i, j;
char array[width][height];
for (i = 0; i < width; i++)
{
for( j = 0; j < height; j++)
{
array[i][j] = '.';
}
}
srand(time(NULL));
for(i=0; i<numOfX; i++)
{
int row = ((rand() % (width-1)) + 0);
int col = ((rand() % (height-1)) + 0);
array[row][col] = 'x';
}
return array;
}
then print out 2d array...
void printEnvironment(int* environment, int width, int height)
{
int i, j;
for (i = 0; i < (height-1) ; i++)
{
printf("\n");
for( j = 0; j < (width-1); j++)
{
printf("%c", environment[i][j]);
}
}
}
int main(int argc, char *argv[])
{
int height = 20;
int width = 80;
int numOfX = 100;
int* environment;
environment = createEnvironment(width, height , numOfX);
printEnvironment(environment, width, height);
system("PAUSE");
return 0;
}

(It looks like you have a stray }, but that's not relevant to the answer)
In your function int* createEnvironment(int width, int height, int numOfX), when you do char array[width][height];, you allocate a width x height block of memory in the stack. Your then use a few for loops that fill in the X's in certain spots. That all looks fine.
The problem is that array is allocated on the stack. Once createEnvironment returns, all of the variables that were placed on the stack will no longer be valid, since those areas of memory might be used by subsequent function calls. An easier way to think about this is to consider where each variable 'lives' within the program. Global variables live in the program and can be accessed by anyone. Variables that live in main can be accessed in main, and in functions that are called by main (i.e. with pointers). However, if you call function A from main, which has some variable V declared, and then call function B from main, B cannot access V, since V only lived in main. The solution to this problem would be to pass V back to main to be sent to B.
Fortunately, the C standard library provides malloc, which allocates memory off the heap, not the stack. When you allocate memory in the heap, it live in the heap regardless of which context it is created from. If function A creates variable V in the heap with malloc, then V can be accessed from main, B, or any other function, so long as a pointer to V is provided. This is also where memory leaks come from; when space is allocated from the heap, if it is not freed with free, then it stays allocated until the program ends.
The short answer is to replace the line char array[width][height]; with char * array = malloc(width * height * sizeof(char));. Not that the sizeof isn't strictly necessary since a char is one byte in size, but that would need to be changed if you changed char to some other type.
You'll also need to update the way you access a sub-element of the array. Since the width and height of the array won't be known if it's in the heap, you'll have to instead provide an offset from array, which should give you a clue how arrays work in C to begin with. I'll leave that for you to figure out.

Related

How call by reference and call by value works on multidimensional pointer arrays?

Can anyone explain me why i dont need -> int ***zd in the init function? Isn't this call by value and the intialization shouldnt stay when i want to print it? Or is a pointer automatically call by reference?
I would love to understand how this exactly works, so if anyone can help me i would highly appreciate it!
#include <stdio.h>
#include <stdlib.h>
void initZD(int **zd, int width, int height){
for(int i = 0; i < width; i++){
for(int j = 0; j < height; j++){
zd[i][j] = rand() % 10;
}
}
return;
}
void printZD(int **zd, int breite, int hoehe){
for(int i = 0; i < breite; i++){
for(int j = 0; j < hoehe; j++){
printf("%d\t",zd[i][j]);
}
printf("\n");
}
}
int main(){
int **zd = NULL;
int width, heigth;
printf("Width: ");
scanf("%d", &width);
printf("Heigth: ");
scanf("%d", &heigth);
//zd = realloc(*zd, breite*sizeof(int));
//zd = calloc(breite, sizeof(int));
zd = malloc(width*sizeof(int));
for(int i = 0; i < width; i++){
//zd[i] = realloc(*zd, hoehe*sizeof(int));
//zd[i] = calloc(hoehe, sizeof(int));
zd[i] = malloc(heigth*sizeof(int));
}
initZD(zd, width, heigth);
printZD(zd, width, heigth);
free(zd);
for(int x = 0; x < width; x++){
free(zd[x]);
}
return 0;
}
initzD does not need the address of zd because it does not change zd. It changes things that are pointed to via zd (specifically things that are pointed to by pointers that zd points to).
To change those things, it needs their addresses, and it has their addresses because they are pointed to by the pointers that zd points to. (Generally, the pointers only point to the first of some number of int, but the subscript operators in zd[i][j] do pointer arithmetic to calculate the addresses of following elements.)
The parameter doesn't need to be defined as int ***zd because you're not modifying the value of the pointer zd in the main function. You're just dereferencing it to modify values that it points to.
Had zd been uninitialized, then you would have to pass a pointer to it so that the function could do the memory allocation that is currently happening in main.
Call by value would mean that a copy of a variable is passed to the function whereas Call by reference would mean that the address of the variable itself is passed.
The implication of this is that changes which are made by operations in the called function would be reflected in the calling function. Arrays in C are passed by reference (by default) as you would pass the array variable to the function which is actually a pointer to the first element of the array.
When you write int ** it actually means you are pointing to an address which is pointing to an element (Hence the **). So if you want to access an integer element of the array you would need to de-reference twice. For the case here:
zd: It is the pointer to the 1st row of the 2D array
zd + i: It is the pointer to the ith row of the 2D array
*(zd + i)/ zd[i]: De-references zd + i to give the address of the base element of the ith row.
Similarly zd[i][j] adds j to the base of the ith row and dereferences it to give the value of the element at ith row and jth column.
Here rules of addition are governed by pointer arithmetic, meaning since an integer occupies 4 bytes of data and if memory is byte organized a pointer to an integer when incremented by 1 would point 4 units ahead of what it pointed to earlier.
Your function initZD doesn't change the pointer int **zd which is passed by value. It not even changes the values of the pointer array where zd points to, but only the values where those pointers point to.
The pointer int **zd = NULL; in main is modified in main only because you allocate the memory there with
zd = malloc(width*sizeof(int));
You would have to pass the address of the pointer to initZD if you would want to allocate the memory inside the function.
Your code contains an error: In main you call free(zd) before you use it to free the other memory with free(zd[x])in the loop. This is undefined behavior.
Example where you would need to pass the pointer by reference, i.e. pass the address of the pointer:
void initZD(int ***zd, int width, int height){
*zd = malloc(width*sizeof(int));
for(int i = 0; i < width; i++){
(*zd)[i] = malloc(heigth*sizeof(int));
}
for(int i = 0; i < width; i++){
for(int j = 0; j < height; j++){
(*zd)[i][j] = rand() % 10;
}
}
return;
}
/* ... */
int main(){
int **zd = NULL;
int width, heigth;
printf("Width: ");
scanf("%d", &width);
printf("Heigth: ");
scanf("%d", &heigth);
initZD(&zd, width, heigth);
printZD(zd, width, heigth);
for(int x = 0; x < width; x++){
free(zd[x]);
}
/* NOTE you must not free this pointer before the loop above */
free(zd);
return 0;
}

3D array in a function

I have a function in C that one of its arguments is 3D array.
when I'm debugging its seems the VS see it as a 2D array, why is it?
this is a program that helps to order goods in containers (boxes).
this specific function is called when its known the this spot is ok to put' and it put it on the 3D matrix.the code:
void put_box(unsigned char space[241][47][48], int x, int y, int z, BOX box, int box_number) {
int i, j, k;
int top_stop;
//cheking if to mark all the hight
if (box.top)
top_stop = 48;
else
top_stop = box.height / 5;
// mark the box
for (i = x; i < x + (box.length / 5); i++)
for (j = y; j < y + (box.width / 5); j++)
for (k = z; k < top_stop; k++)
space[i][j][k] = (unsigned char)box_number;
}/*void put_box*/
I expect to see on the locals window the 3D array but I see only 2.
and its effect the writing to the matrix.
When you pass arrays to functions, they are passed as pointers. More specifically pointer to the arrays first element.
So for the argument declaration unsigned char space[241][47][48] the compiler really sees it as unsigned char (*space)[47][48].
Probably because the first array dimension is not part of the func prototype, so the debugger is likely to be looking at the first slice only.
void put_box(unsigned char space[][47][48], <snip> )
I'm guessing that if however you stick a breakpoint in this method, you'd see the full array (but you'll only see one slice when you step into put_box)
int main()
{
unsigned char space[99][47][48];
put_box(space, <snip>);
return 0;
}

Dynamic memory allocation repetition in C

I am somewhat new to C programming. I have a doubt regarding dynamic memory allocation. The following is a code in the main program for memory allocation.
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
I want to call the function and create elements in the matrix inside the function. Do I have once again allocation memory inside the function like below or Is there any other method to avoid this tedious memory allocation repetition. Following is the function.
`double** create_square_matrix(int n)
{
int i,j,sum=0;
double **array2=(double**)malloc(sizeof(double*)*n);
array2[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
array2[i] = array2[i-1] + n;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
sum=sum+j;
array2[i][j]=sum;
}
}
return array2;
}
`
The above function returns the array which is stored in the 'mat' variable. And another question is how do I free the memory of variable 'array2' inside the function after using the return method. I can't free the memory possibly before returning the array. Is there a method to free the memory in the above function.
Your function create_square_matrix allocates memory and then fills it by some values.
Your top piece of code allocates memory, and then calls create_square_matrix which again allocates memory. It is like to mop floors before calling the janitor who also mops floors. You don't need to allocate memory twice. Not only it is unneccessary, in fact it is bad. Since you perform two allocations, the memory from the first one is lost, and there is no way to free it. This is called memory leak. Instead of
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
you should write
double **mat = create_square_matrix(n);
As mentioned, in C there's no need to cast to/from void*. Also, your calloc is backwards: use N elements for the first argument, sizeof(element) for the second.
I will answer your question, and then suggest a better approach.
You are choosing double ** for your matrix. Even if it weren't square, you know exactly how many pointers and how many doubles you need, and of course how big each type is. So,
double **M = malloc( n * sizeof(double*) + n * m * sizeof(double) );
does the trick, does it not? If sizeof(double*) == sizeof(double) for your machine (probably true), then
double **M = calloc( (1+n) * m, sizeof(double) );
works, too, but less portably. You also get the zeros for free; you'll have trouble finding a machine for which it's not true that double f=0 yields a value for which all bits are zero.
But why define your matrix as an array of pointers? Why not instead define it as an array of doubles?
double *M = calloc( n * m, sizeof(double) );
Better yet, for the past 15 years or so, C has supported variable-length arrays, meaning you can define arrays whose size is determined at runtime. Back in K&R days, you could define an array M[n] unless n was a static constant or enum. If your arrays aren't ginormous -- meaning that for the machine in question they'll fit comfortably on the stack -- you can skip malloc and simply define your matrix by a size determined at runtime.
Even if you can't do that, can typedef one dimension dynamically,
typedef double (x_axis_t)[m];
double x_axis_t *M = calloc( n * sizeof(x_axis_t), sizeof(double) );
which is nice, because then you can access your array as
M[x][y];
Just don't try to use M[x,y], because that's something else altogether.
BTW, since you're new to the game, to use a c99 compiler, the standard command is c99, not cc. See your friendly manual for details. :-)
Using a nice function macro for memory allocation is always a good idea. Unless you have to free memory manually I would leave it to a garbage collector such as libgc. Below is an example. If you don't want to use a garbage collector you can just replace GC_MALLOC with malloc. When you free the array (manually) you must first free the individual rows.
#include <gc/gc.h>
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = GC_MALLOC((n) * sizeof (ptr)[0])
double **SquareMatrix(int n)
{
double **A;
int i, j;
NEW_ARRAY(A, n);
for (i = 0; i < n; i++) {
NEW_ARRAY(A[i], n);
for (j = 0; j < n; j++) {
A[i][j] = 0.0;
}
}
return A;
}
int main(void)
{
const int n = 5;
double **A;
int i, j;
A = SquareMatrix(n);
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%5.2f ", A[i][j]);
}
putchar('\n');
}
return 0;
}

Pointers to Dynamic Arrays in C

I am trying to learn how to create a function that will take a dynamic int array (int arrayPtr = (int) malloc...) and replace it with another dynamic array. This new array will not simply be of different values, but potentially a different number of elements.
From my research, I've learned that I need to pass into this function a reference to my array pointer, rather than the pointer itself (&arrayPtr). That means the function signature needs to have int **arrayPtr instead of int *arrayPtr.
I feel like it makes sense to me; We need to tell arrayPtr to point to a different location in memory, so we need the memory address of arrayPtr rather than its value (the memory address of the original array);
I wrote a little test program to see if I understood, but I cannot get it to work. Using debugging, I've observed the following: From within the function, the (int **arrayPtr) doesn't represent the entire array, but just the first element. That is, I can get the value 500 if I do *arrayPtr[0], but *arrayPtr[1] is inaccessible memory.
Here is my test program:
#include <stdlib.h>
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = (int *)malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = *arrayPtr[i] * 2;
}
free(arrayPtr);
arrayPtr = &tempArrayPtr;
return;
}
int main(int argc, char **argv) {
int i;
int arrayLength = 2;
int *arrayPtr;
arrayPtr = (int*)malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
arrayPtr[i] = i + 500;
}
replaceArray(&arrayPtr, arrayLength);
exit(EXIT_SUCCESS);
}
The function is supposed create a new array with the value of each element of the original array doubled, and have the arrayPtr variable in the calling function refer to the new array instead. As i have written it, however, it gets SIGSEGV when the replaceArray function tries to access *arrayPtr[1].
I realize that this little demonstration program is not doing anything that requires the behavior that I'm testing. It is just so that I can understand the concept with a simple example.
Since this is a tiny, trivial, program, I feel justified in that the answer that I accept will contain the complete working version of this code.
There have to be three changes in you code:
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = (*arrayPtr)[i] * 2;//In this if you use the without braces it will acts array of pointers that is pointing to a array. So we have to get the value from that using that braces.
}
free(*arrayPtr);//<< here we have to free the memory of arrayPtr not the address of the &arrayPtr.
*arrayPtr = tempArrayPtr; // Here you have to assign the address to that value of arrayPtr.
return;
}
There is no need the type cast the return value of malloc.
Both of these lines are wrong:
free(arrayPtr);
arrayPtr = &tempArrayPtr;
The first line passes the address of your variable to free(), rather than the address of the actual allocated array. Since the variable is on the stack rather than mallocated, free() will crash or abort here. What you want to do instead is free(*arrayPtr):.
The second line merely sets the local variable arrayPtr to the address of the variable tempArrayPtr. What you want to do instead is *arrayPtr = tempArrayPtr;.
See the below code and the inline comments.
#include <stdlib.h>
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = malloc(sizeof(int) * arrayLength); //do not cast
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = (*arrayPtr)[i] * 2;
}
free(*arrayPtr); // free the *arrayPtr, [which is `arrayPtr` from `main`]
*arrayPtr = tempArrayPtr; //copy tempArrayPtr and put it into *arrayPtr
return;
}
int main(int argc, char **argv) {
int i;
int arrayLength = 2;
int *arrayPtr;
arrayPtr = malloc(sizeof(int) * arrayLength); // do not cast
for (i = 0; i < arrayLength; ++i) {
arrayPtr[i] = i + 500;
}
replaceArray(&arrayPtr, arrayLength);
exit(EXIT_SUCCESS);
}

How to use pointers in C/ returning an int array?

I'm currently trying to write the code for a simple Quicksort in C, but I can't seem to understand C syntax and pointers. I'm used to coding in Java, so I'm a little confused on how to return int arrays, and what I'm doing wrong.
Here is my code right now, any help would be greatly appreciated.
#include <stdio.h>
#define MAX 100
int input[MAX];
int* QuickSort(int A[], int n);
int* combine (int first[], int pivot, int last[]);
//main method to run program
int main()
{
int i, n;
//read in input and store values in array named input
printf ("Enter several numbers separated by spaces or returnsand ended by Ctrl-D:\n");
for (n = 0; n < MAX && scanf("%d", &input[n]) != EOF; n++);
//runs QuickSort on the array
int new[n] = QuickSort(input, n);
printf("Here is your sorted array:\n");
//goes through sorted array to print values
for (i = 0; i < n; i++)
printf("%d\n", new[i]);
}
int* QuickSort(int A[], int n)
{
//if array has 1 value or is empty, automatically return
if (n <= 1)
return A;
int pivot = A[0];
int less[n/2];
int more[n/2];
int lesscount = 0;
int morecount = 0;
int i;
for (i = 1; i<n; i++)
{
if (A[i] <= pivot)
{
less[lesscount] = A[i];
lesscount++;
}
else if (A[i] > pivot)
{
more[morecount] = A[i];
morecount++;
}
}
int size = n/2;
return combine(QuickSort(less, size), pivot, QuickSort(more, size));
}
int* combine (int first[], int pivot, int last[])
{
int firstsize = sizeof(first)/sizeof(first[0]);
int lastsize = sizeof(last)/sizeof(last[0]);
int totalsize = firstsize + lastsize + 1;
int combined[totalsize];
int n;
for (n =0; n<firstsize; n++)
{
combined[n]= first[n];
}
combined[n]=pivot;
n++;
int m;
for (m =0; m<totalsize; m++)
{
combined[n] = last[m];
n++;
}
return combined;
}
The basics
A pointer is a memory address which you can dereference and access. It's very different from an object and is (mostly likely) just an 8-byte value. Whereas in Java you might be able to pass around objects (which do point to some memory somewhere), in C you must be a lot more careful about what memory you're pointing.
In particular, there is a difference between the stack and the heap. The stack is what your program uses to track local variables and will automatically allocate space. On the other hand, the heap is usually something you need to manage yourself. In particular, you won't get heap addresses unless you explicitly allocate it (i.e., with malloc). Why the distinction? Because the stack automatically allocates space, but also automatically deallocates space on function return.
Why does this apply to you?
Let's take a look on some of your functions:
int* combine (int first[], int pivot, int last[])
/* i.e., int* combine (int *first, int pivot, int *last) */
{
int firstsize = sizeof(first)/sizeof(first[0]);
int lastsize = sizeof(last)/sizeof(last[0]);
int totalsize = firstsize + lastsize + 1;
int combined[totalsize];
/* The rest of the code */
return combined;
}
You're returning combined, a stack allocated variable to whoever is calling your function. While doing this is "legal" in the strict sense, it's not correct because once you've returned from the function, the program will automatically deallocate the memory. This means you're probably getting some very confusing results and/or faults.
Now, how do you fix this?
In your case, quicksort doesn't need more space, just some clever manipulation of variables. Thus, you actually don't even need to use any of the sub arrays, nor do you need to return any arrays. The neat thing about pointers is that you get an address to memory. Thus, if you change that is pointed to (i.e., A[0] = x), then any other function which also knows about A will see that update.
And applied to quicksort?
Your initial implementation isn't quite correct either. Quicksort can be roughly broken down into two steps: partition and combine. When you partition, you want to separate all values less than a pivot value from all values greater than a pivot value. However, because you don't already know how many that is, assuming you'll have size/2 in each partition is going to cause you trouble.
For partition, you can use an in place iterative method. Something like this:
while index < end:
if A[index] < pivot:
index ++
else if A[index] > pivot:
swap(A[index], A[end])
end --
swap(pivot, A[index])
(There may be some off by one errors in the above.) The basic idea is that by keeping track of both a lower part and an upper part with two indices, you "add" the current value you're comparing against to the proper side (by moving to the next index, or swapping and decrementing the end). And by doing this in place, you don't need to deal with memory allocation.
The recursive step then becomes knowing where your sub-pieces are and recursively calling sort of each.

Resources