C arrays and functions, how to return? - c

I have a newbie question regarding array and functions in C.
Let's say I have this array:
int array1[10] = {2,4,6,3,2,3,6,7,9,1};
I wrote this function:
int *reverseArray(int *array, int size)
{
int *arr = malloc(size * sizeof(int));
int i, j;
for(i = 10, j = 0; i > 0; i--, i++) {
arr[j] = array[i];
}
return arr;
}
I don't even know if it works, because if I do:
array1 = reverseArray(array1, 10);
I got the error:
assignment to expression with array type
How do I assign the adress of an array to another array?

The function is correct*, and it works fine. The problem is that you cannot assign an array like this:
array1 = reverseArray(array1, 10);
reverseArray returns a pointer, so you should assign it to a pointer variable:
int* reversedArray1 = reverseArray(array1, 10);
If you want the data to be placed back in array1, use memcpy:
memcpy(array1, reversedArray1, sizeof(array1));
free(reversedArray1);
Note that since your function uses malloc to allocate its return value, the caller needs to deallocate this memory after it is done with it. You need to call free(reversedArray1) to ensure that the allocated array does not create a memory leak.
* Use size-1 in place of 10 in the for loop header, since you are passing it anyway, and allow i to reach zero:
for(i = size-1, j = 0; i >= 0; i--, j++)

Related

New beginner for dynamically allocated Array. Why do I have segmentation fault here?

I use nested data structure for fibonacci, but I have a segmentation fault 11.
void fib(int **fib_array, int n){
fib_array = malloc(n * sizeof(int*));
for(int i = 0; i < n; i++){
fib_array[i] = malloc(sizeof(int));
}
for(int i = 0; i < n; i++){
if (i <= 1){
fib_array[i][0] = i;
}
else{
fib_array[i][0] = fib_array[i - 2][0] + fib_array[i - 1][0];
}
}
}
int main(int argc, char **argv) {
/* do not change this main function */
int count = strtol(argv[1], NULL, 10);
int *fib_sequence;
fib(&fib_sequence, count);
for (int i = 0; i < count; i++) {
printf("%d ", fib_sequence[i]);
}
free(fib_sequence);
return 0;
}
you are being too complicated. You just need a single malloc
*fib_array = malloc(n * sizeof(int));
and remove you second indexings [0] from everywhere
The consfusion comes from **int. This looks like a multi dim array. Its not - its declared ** so that you can set the value in the caller. A simpler exampe will help
void Make42(int* v)
{
*v = 42;
}
int main()
{
int myv = 0;
Make42(&myv);
// now myv == 42
}
The * in the arg list is so that Make42 can 'reach out' and modify what was passed to it (myv in this case)
In your code the ** on fib array is there for the same purpose. you could have done (In know you werent allowed to by the test definition )
int *fib(int n){
int *fib_array = malloc(n * sizeof(int));
......
return fib_array;
}
and in main
fib_sequence = fib(count);
this makes it much clearer that you are really manipulating a simple array
pm100 is right, but a little short for answering to a beginner...
At first, you have passed a pointer to a pointer. If you want the original pointer to contain a value, you need to dereference the pointer to pointer:
*fib_array = ...
By assigning to the pointer only (as you did in your code), you do not modify the orignial pointer (fib_sequence in main) at all. And as you have not initialised it, it might point to anywhere, thus the segmentation fault when you try to print the values of it.
Then why an array of pointers to individually stored values? You can use a contiguous array of ints, which you get by
*fib_array = malloc(n * sizeof(int));
OK, further usage won't be too nice ((*fib_array)[i] = ...), so I recommend a temporary variable instead:
int* fa = malloc(n * sizeof(int));
// now fill in the values comfortably:
fa[i] = ...;
// finally, assign the pointer to the target:
*fib_array = fa;
Side note: always check the result of malloc, it could be NULL:
fa = ...
if(fa)
// assign values
else
// appropriate error handling
In your concrete case, you could omit the else branch in your function and check your pointer outside within main function.
By the way, a simple return value would have made your live easier, too:
int* fib(int n)
{
int* fib_array = malloc(n * sizeof(int*));
// ...
return fib_array;
}
Notice: no need for pointer to pointer... Usage:
int* fib_sequence = fib(count);

Reallocating memory for a two dimensional array in C

My goal is to dynamically reallocate memory for a two dimensional int array in C. I know there are already several questions about that topic, but unfortunately my code does not run properly and i don't know what is going wrong.
First i am allocating memory:
int n = 10;
int m = 4;
int** twoDimArray;
twoDimArray = (int**)malloc(n * sizeof(int*));
for(int i = 0; i < n; i++) {
twoDimArray[i] = (int*)malloc(m * sizeof(int));
}
And initializing the array with integer numbers:
for(int i = 0; i < n; i++) {
for(j = 0; j < 4; j++) {
twoDimArray[i][j] = i * j;
}
}
Then i use realloc() to reallocate memory dynamically:
int plus = 10;
int newArraySize = n + plus;
twoDimArray = (int**)realloc(twoDimArray, newArraySize * sizeof(int));
I am expecting my aray twoDimArray to be accessible at [10][0] now, but when running
printf("twoDimArray[10][0] = %d\n", twoDimArray[10][0]);
i get an "EXC_BAD_ACCESS" runtime error.
Probably i am missing something rather simple, but since i am new to C and can't figure out my mistake. Any help is appreciated.
reallocating the array of pointers is necessary, but then you have only n values that point to something valid. You need to allocate the rest of the sub-arrays because the newly allocated memory points to unallocated/invalid areas. The error is not from accessing the pointer, but from dereferencing it.
You need to add something like:
for(int i = n; i < n+plus; i++) {
twoDimArray[i] = malloc(m * sizeof(int));
}
(same goes for deallocation: first deallocate the arrays in a loop, then deallocate the array of pointers)
Aside:
assigning the result of realloc directly to the original variable can be a problem if realloc returns NULL. Even if it's rare in those resizing cases (Under what circumstances can malloc return NULL?), you should copy the result in a temp variable, check for NULL, and free the old pointer if reallocation failed.
Do I cast the result of malloc?

Setting Dynamic arrays equal to eachother in C

int staticArrayA[10];
int staticArrayB[10];
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = (int *)malloc(sizeof(int) * 10);
From what I understand, the value of staticArrayA is a pointer to the 1st element in the array, however the pointer that represents this base address behaves like a const pointer and cannot be changed, in which case it makes sense that you cannot set:
staticArrayA = staticArrayB;
But what about dynamic arrays? if they are both just pointers to a contiguous block of bytes in memory, then why can't you set them equal to eachother?
dynamicArrayA = dynamicArrayB;
It seems like the address that dynamicArrayA points to would now be the same address that dynamicArrayB points to. Please give me some insight. Perhaps I am wrong, but here is what I was trying to do:
/* remove any element that is 0 from array. n is size of array */
void compressArray(int *array, int n) {
int size = n;
int index = 0;
int *nuArray = (int *)malloc(sizeof(int) * n);
assert(nuArray != NULL);
for (int i = 0; i < n; i++) {
if (array[i] != 0) {
nuArray[index] = array[i];
index++;
size--;
}
}
nuArray = realloc(nuArray, sizeof(int) * size);
assert(nuArray != NULL);
array = realloc(array, sizeof(int) * size);
assert(array != NULL);
array = nuArray; //This doesn't seem to work
free(nuArray);
}
int main(int argc, const char * argv[]) {
int *array = (int *)malloc(sizeof(int) * 10);
assert(array != NULL);
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
array[i] = 0;
} else {
array[i] = i;
}
}
compressArray(array, 10);
return 0;
}
I am sure that there are much simpler and more elegant ways to write the function, and i know that I can copy all the elements of nuArray into array and then use realloc() to reduce the size, however, I am just hoping someone can give some insight into the nature of dynamic arrays and explain some of this behavior and tell me why the assignment does not work, or if there are cases in which it does. Also, i could have the function return an int * and set array = to this function call and that works, however why can't i do it inside the function? Thanks for your time and for any help.
if they are both just pointers to a contiguous block of bytes in memory, then why can't you set them equal to each other?
Of course you can. You just have to know the ramifications.
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = dynamicArrayA;
Now dynamicArrayB and dynamicArrayA point to the same memory. You change the value of what one points to, the change will be visible through other pointer too.
dynamicArrayB[0] = 10; // dynamicArrayA[0] is 10.
dynamicArrayA[5] = 15; // dynamicArrayB[5] is 15.
If that's your objective, you can do that without any problem.
Update, in response to OP's comment
The line
array = nuArray; //This doesn't seem to work
changes the value of array locally in compressArray. That does not change the value of array in main.
You'll have to come up with a different method to return nuArray back to main.
One solution to the problem would be to change the return type of compressArray from void to char* and return nuArray from the function.
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = (int *)malloc(sizeof(int) * 10);
After this if you do this ( which ofcourse is possible ) -
dynamicArrayA = dynamicArrayB; //you want this then don't allocate memory to dynamicArrayA
Now , dynamicArrayA won't point to memory allocate by malloc to it previously , so you won't be able to free that memory block . Thus , can lead to memory leak.
You can use memcpy for this task -
/* allocate memory to both dynamicArrayA and to dynamicArrayB */
for(int i=0;i<10;i++){
dynamicArrayA[i]=i+1; // store value in dynamicArrayA
}
memcpy(dynamicArrayB,dynamicArrayA,sizeof(int)*10); //copy it to dynamicArrayB
for(int i=0;i<10;i++)
printf("%d",dynamicArrayB[i]); // print values
free(dynamicArrayA);
free(dynamicArrayB);
Let's take a look at what's actually happening at the end of compressArray:
array = nuArray;
After this statement, array now points to the same memory that nuArray points to. The memory that array previously pointed to is now accessible inside of compressArray, however array in main still points to the original memory block. That's because the address of this block is what was passed to compressArray, not the address of the array variable.
free(nuArray);
This frees the memory pointed to by nuArray. But since array contains the same value as nuArray, i.e. the address of the memory block pointed to by nuArray, now array points to a freed block of memory, and accessing it is undefined behavior.
When the function returns, the value of array in main is unchanged. That's because the value of array was passed in.
For this to work as expected, compressArray needs to take the address of a pointer (an int **) and change what that points to:
void compressArray(int **array, int n) { // "array" is a pointer to an array
int size = n;
int index = 0;
int *nuArray = (int *)malloc(sizeof(int) * n);
assert(nuArray != NULL);
for (int i = 0; i < n; i++) {
if ((*array)[i] != 0) { // note how we're now accessing the array
nuArray[index] = (*array)[i]; // same here
index++;
size--;
}
}
nuArray = realloc(nuArray, sizeof(int) * size);
assert(nuArray != NULL);
free(*array); // We don't need the memory array pointed to anymore, so free it
*array = nuArray; // This changes "array" in main. Also, don't free nuArray,
// otherwise *array will also point to freed memory
}
Then you call it like this:
compressArray(&array, 10);
// print the new contents of array
free(array); // We're done with it now, so free it

Is there anyway to memset over a triple pointer?

For a variety of reasons I have a list of objects that I need passed around in the form of a triple pointer. I declared it like so.
List=((Entity***) malloc(sizeof(Entity) * 32));
Every cycle of this list being passed around requires the entire list to be wiped which I attempted using the line below.
memset(&***List,0,sizeof(Entity) * 32);
The end result of that method is an Access violation error. What can I do to get around this?
Suppose you are declaring a dynamically allocated three-dimensional array List[M][N][K], the correct way to initialize it is:
List = (Entity***)malloc(sizeof(Entity**) * M);
for (int i = 0; i < M; ++i) {
List[i] = (Entity**)malloc(sizeof(Entity*) * N);
for (int j = 0; j < N; ++j) {
List[i][j] = (Entity*)malloc(sizeof(Entity) * K);
for (int k = 0; k < K; ++k) {
memset(&List[i][j][k], 0, sizeof(Entity));
}
}
}
But suppose you are to initialize a statically allocated array like above, you should make M, N, K constants that can be determined at compile time and declare Entity List[M][N][K] directly. Thus you can initialize it as:
memset(List, 0, sizeof(Entity) * M * N * K);
Yes, there is mistake in your code. I like to explain with simple code
int main(void){
char ***List = NULL;
List=malloc(sizeof(char **) * 32); //step1
List[0]= malloc(sizeof(char *) * 32);//step2
List[0][0]=malloc(sizeof(char) * 32);//step3
memset(&List[0][0][0],0,sizeof(char) * 32); //step4
return 0;
}
After doing step1, you are trying to do step4. But there is step2&3 that you have missed. Which means you have allocated memory for 3D pointer only. Without allocating 1D memory memset is done for 1D pointer.

How to declare pointer and allocate memory a two-dimensional array and pass to a function

I want to declare the correct pointer and allocate memory for a two-dimensional array, and correctly pass to a function. I am having trouble getting this to work properly and need help.
Here is my code:
double **podrucje;
podrucje=(double **) malloc (sizeof (double *) *123);
for (i=0;i<(123);i++)
{
podrucje[i]=(double *) malloc (sizeof (double) * 11);
}
for (i=0;i<(123);i++)
{
memset (podrucje[i], 0, 10);
}
But this code doesnt work, it messes up whole my program. So i decided to give up on dynamic allocation and use this:
double podrucje[123][11]={0};
But i dont know how to send it and use it in function...
memset works on per byte basis.
double **podrucje = (double **) malloc (sizeof (double *) * 123);
for (i = 0; i < 123; i++)
{
podrucje[i] = (double *) malloc (sizeof (double) * 11);
memset(podrucje[i], 0, sizeof(double) * 11);
}
if you want to pass it just declare it as such
void function(double podrucje[123][11]) {
...
}
You're best off to use malloc, but allocate the whole array on your second line, so it all gets allocated in contiguous memory. So
podrucje = (double*) malloc (sizeof (double) * 123 * 11);
Then the first loop can go away too. And it looks like you're initializing the array to 0 -- in that case, use calloc instead of malloc, eliminating the second loop.
To index into the array, use things like
double myitem = podrucje [11 * row + col];
You should of course use a define or similar to keep the use of 11 consistent, but that's not the point of this answer.
Write the function argument the same way you wrote the variable definition:
void myfunc(double podrucje[123][11])
{
...
}
double podrucje[123][11];
myfunc(podrucje);
Note that the array is passed "by reference" rather than being copied.
In the following code snippet,
podrucje[i]=(double *) malloc (sizeof (double) * 11);
for (i=0;i<(123);i++)
{
memset (podrucje[i], 0, 10);
}
1) You dont need the extra parenthesis against the numbers 123 and 11
The for loop can be as follows,
for (i = 0; i < 123; i++)
2) Instead of using 123 and 11. Try to define a MACRO and use that instead.
Advantage: The code becomes independent of special numbers and is easily maintainable. Especially in the cases of larger code base.
3) If you read the code, podrucje[i] is allocated a memory of 11 doubles But when you memset you are setting it for only 10 doubles while the last one may or may not consist of garbage. Use calloc here, It not only allocated memory but also initializes the same.
podrucje[i]=(double *) calloc(11,sizeof(double));
Also It could be more helpful if you could tell How exactly is it screwing up your code ?
Example, Code Snippet could help more than just stating its screwing up.
It helps others to investigate and solve the issue.
If you have a modern C compiler (C99 would do) you can even declare real 2D matrices with variable sizes. You don't need to fall back to this awful emulation with pointers.
void myfunc(size_t n, size_t m, double podrucje[n][m])
{
...
}
double (*podrucje)[n] = malloc(sizeof(double[n][m]));
myfunc(n, m, podrucje);
For the function you just have to ensure that the declarations of n and m come first, before the matrix.
There are several ways to dynamically allocate memory for an NxM array. Here are two:
You can declare a pointer to an M-element array, and then malloc N instances of it:
double (*podrucje)[11] = malloc(sizeof *podrucje * 123);
As of C89, you don't need to cast the result of malloc, and the practice is discouraged. Also, note that the operand to sizeof is the expression *podrucje; this gives me the same result as sizeof (double) * 11.
You would index this array as podrucje[i][j] like any other 2D array. podrucje[i] implicitly dereferences the pointer (remember that a[i] is equivalent to *(a + i)) so you don't have to do anything funky with it.
You would use it in a function as follows:
void init(double (*podrucje)[11], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < 11; j++)
podrucje[i][j] = 0.0;
}
which would be called as
init(podrucje, 123);
The drawback to this method is that the function can only operate on Nx11 arrays; if you're using a C99 compiler or a C2011 compiler that supports variable length arrays, you could specify the number of columns as a runtime variable:
void foo(void)
{
size_t rows = 123, cols = 11;
double (*podrucje)[cols] = malloc(sizeof *podrucje * rows);
if (podrucje)
init(cols, podrucje, rows);
...
}
// cols must be declared before it can be used
// in an array declarator
//
void init(size_t cols, double(*podrucje)[cols], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
podrucje[i][j] = 0.0;
}
When you're done with the array, deallocate it as follows:
free(podrucje);
The other approach is to allocate each row separately, as follows:
size_t rows = 123, cols = 11;
double **podrucje = malloc(sizeof *podrucje * rows);
if (!podrucje)
{
// malloc failed; handle allocation error here
}
else
{
size_t i;
for (i = 0; i < rows; i++)
{
podrucje[i] = malloc(sizeof *podrucje[i] * cols);
if (!podrucje[i])
{
// malloc failed; handle allocation error here
}
}
}
And you would use it in a function as follows:
void foo()
{
double **podrucje;
// allocate array as above
init(foo, rows, cols);
...
}
void init(double **podrucje, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
podrucje[i][j] = 0.0;
}
When you're finished with the array, deallocate it as follows:
for(i = 0; i < rows; i++)
free(podrucje[i]);
free(podrucje);
The first method allocates memory as a single, contiguous block; the second allocates it in a series of smaller, discontinuous chunks. If your array is especially big or your heap especially fragmented, the first method may fail where the second will succeed. If you're working with a compiler that doesn't support variable-length arrays, the first method is much less flexible, because the number of columns must be specified at compile time.
How could the same indexing method work for both forms?
In the first case, each podrucje[i] is an 11-element array of double; indexing it with j works like any other array. In the second case, each podrucje[i] is a pointer to double. Since a[i] is evaluated as *(a + i), array indexing works on pointer expressions just as well as array expressions.
int print_func(char((*p)[26])[10])
{
int i = 0;
for (i=0; i < 26 ; i++) {
fprintf(stderr, "%02d:%.*s\n", i, 10, p[0][i]);
}
return (0);
}
int main(void)
{
int nrow = 26;
int ncol = 10;
char((*p)[26])[10] = (char((*)[26])[10])(0);
char(*q)[10];
char c = 'a';
int i = 0;
p = (char((*)[26])[10])malloc(sizeof(char) * nrow * ncol);
if ((char((*)[26])[10])0 == p) {
return (-1);
}
for (i=0, q=p[0]; i < nrow ; i++) {
memset(q, c, sizeof(char) * ncol);
c++;
q++;
}
for (i=0,q=p[0] ; i < nrow ; i++) {
fprintf(stderr, "%.*s\n", 10, q);
q++;
}
p[0][8][0]='z';
getchar();
print_func(p);
return (0);
}

Resources