Cannot return int array - c

I want to use only studio.h library to convert from decimal number to binary number by using an array to store remainder but the result is not correct, maybe i have problem with memory allocation or return value is wrong, please help me to check it.
Thank you so much!
#include <stdio.h>
int n = 0;
int* DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
void main(){
int *d1 = DecimalToBinary(5);
int *d2 = DecimalToBinary(10);
for(int i = n-1 ;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
for(int i = n-1 ;i>=0;i--)
printf(" %d",d2[i]);
}

You return a pointer to a local array. That local array is on the stack, and when the function returns the array goes out of scope and that stack memory will be reused when you call the next function. This means that the pointer will now point to some other data, and not the original array.
There are two solutions to this:
Declare the array in the function calling DecimalToBinary and pass it as an argument.
Create the array dynamically on the heap (e.g. with malloc) and return that pointer.
The problem with method 2 is that it might create a memory leak if you don't free the returned pointer.
As noted by Craig there is a third solution, to make the array static inside the function. However in this case it brings other and bigger problems than the two solutions I originally listed, and that's why I didn't list it.
There is also another serious problem with the code, as noted by Uchia Itachi, and that is that the array is indexed by a global variable. If the DecimalToBinary function is called with a too big number, or to many times, this global index variable will be to big for the array and will be out of bounds for the array.
Both the problem with dereferencing a pointer to an out-of-scope array and the indexing out of bounds leads to undefined behavior. Undefined behavior will, if you're lucky, just lead to the wrong result being printed. If you're unlucky it will cause the program to crash.

You are returning a pointer to a locally allocated array. It is allocated on the stack, and goes away when the function returns, leaving your pointer pointing to garbage.
You have a few options. You could pass an array in to fill:
void DecimalToBinary(int result[10],int number){
while(number!=0){
result[n++] = number%2;
number/=2;
}
return result;
}
// usage example:
int b[10];
DecimalToBinary(b, 42);
Or you could allocate an array on the heap:
int* DecimalToBinary(int number){
int *a = (int *)malloc(sizeof(int) * 10);
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
// usage example
int *b = DecimalToBinary(42);
free(b); // when finished with it
Or you could wrap the array in a struct:
typedef struct {
int b[10];
} result;
result DecimalToBinary(int number){
result r;
while(number!=0){
r.b[n++] = number%2;
number/=2;
}
return r;
}
// usage example
result r = DecimalToBinary(42);
If you do the malloc() option, do not forget to free() the returned data when you're done with it, otherwise it will hang around. This is called a memory leak. In more complex programs, it can lead to serious issues.
Note: By the way, if your number is larger than 1023 (10 binary digits), you'll overrun the array. You may also wish to explicitly stop once you've stored 10 digits, or pass the size of the array in, or compute the required size first and allocate that much space. Also, you will get some odd results if your number is negative, you might want to use number&1 instead of number%2.
Note 2: As noted elsewhere, you should make n local, or at the very least reinitalize it to 0 each time the function is called, otherwise it will just accumulate and eventually you'll go past the end of the array.

int[10] is not the same as int *; not only is the former created on the stack, it is a different type alltogether. You need to create an actual int * like so:
int *a = malloc (10 * sizeof (int));
Of course, don't forget to free() it after use!

What you can also do and what is commonly done in C is creating the array where it is called and provide a pointer to that array to the function, this way when the array is on the stack of the function that calls it and not in the function self. We also have to specify the size of the array on to that function, since the function cannot know to how many elements the pointer points to
void DecimalToBinary( int number, int* output, unsigned size ) {
/*adapt this to your liking*/
int i;
for ( i = 0; i < size && number != 0; i++) {
output[i] = number%2;
number/2;
}
}
and in you main function you would call it like this:
int array[10];
DecimalToBinary( 5, array, sizeof(array)/sizeof(array[0]));
now array has the same result as a would have had in your example.

The problem in your code lies here..
int * DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
The array a scope is only till this function. Once this function terminates, the memory allocated for this array will be released, either u need to use dynamic memory allocation or make array a global.

This is the correct program:
#include <stdio.h>
int n = 0;
int a[10] = {0};
int* DecimalToBinary(int number){
n = 0;
while(number!=0){
a[n++] = number%2;
number = number/2;
}
return a;
}
int main(){
int *d1;
int *d2;
int i;
d1 = DecimalToBinary(5);
for(i = n-1;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
d2 = DecimalToBinary(10);
for(i = n-1;i>=0;i--)
printf(" %d",d2[i]);
printf("\n");
}

Related

Releasing pointer memory aswell as pointer itself

A "Deeltal" keeps track of how many dividers an integer has (count) and keeps them in an array (dividers).
Examples:
value = 8 -> count = 3 and dividers = {1,2,4}
value = 10, count = 3, dividers = {1,2,5}
Hope everything is clear, take a look at the following code:
typedef struct{
int value;
int count;
int* dividers;
} Deeltal;
void free_dividers(Deeltal *g){ /*Deletes the int* dividers of a given Deeltal*/
free (g - > dividers);
}
/* the following two functions have the same purpose: deleting the content of a
given amount of "Deeltal" AND deleting the pointer to it aswell*/
void free_amountOfdeeltal(Deeltal *d, int amount){
int i;
for (i = 0; i < amount; i++){
free_dividers(&d[i]);
}
free(d);
}
void free_amountOfdeeltalVersion2(Deeltal **g, int amount){
int i;
for(i = 0; i < amount; i++){
free_dividers(&(*g)[i]);
}
free(*g);
}
If my main looked something like this
int main(void){
/*EDIT 3/11/2017: forgot to allocate memory for *d and initializing g.
Thanks for pointing this out*/
Deeltal g = 0;
g.value = 6; g.count = 3; g.dividers = {1,2,3};
Deeltal *d = malloc(sizeof(Deeltal));
d->value = 6; d->count = 3; d->dividers = {1,2,3};
free_amountOfdeeltal(&g);
free_amountOfdeeltalVersion2(&d);
}
What is the difference between free_amountOfdeeltal and free_amountOfdeeltalVersion2?
Both should do the same thing: releasing the memory of a Deeltal and also deleting the pointer pointing to that memory.
On a sidenote:
How do you delete the memory as well as the pointer?
Not withstanding calling this function with invalid data as pointed out by others .. I'll attempt to answer the question I think you are asking.
On a sidenote: How do you delete the memory as well as the pointer?
You can't really "delete the pointer" in this context as a pointer is simply a variable that is assigned an address. You delete memory that was allocated to you by passing free a pointer to the memory. Note that free does not modify the value of the pointer at all. (It can't because the pointer is passed by value.) After the call to free the pointer still points to the same memory address.
If what you mean is "how can I assign a meaningful value to the pointer to identify that its memory has already been deleted," then you can use the second form of your function:
void free_amountOfdeeltalVersion2(Deeltal **g, int amount);
and set *g to NULL before returning. You can then use this information than the pointer is NULL to identify the memory has already been deleted.
You didn't allocate any memory for d so your pointer doesn't point to any structure. Therefor, you can't access its properties or free its memory because you didn't reserve it in the first place. There's no way this code could come remotely close to compiling.
First of all you should be allocating memory for a "Deeltal" structure like this:
Deeltal *d = malloc(sizeof(Deeltal));
I recommend you go back and relearn how pointers work, as you're doing some really weird stuff there.

C: Free temporary array produced by malloc-function

I have a c function that produces my a int array using malloc. It works quiet well and I think it isn't really important what it does because the problem doesn't really have anything to do with that. (In this case it calculates the numbers to a given int and base). I need this array temporary in a function, which might be a sub function of a sub function of a ... (you got the idea, point this function can be used several times) and before the return I would like to run free, but it doesn't work. Here is a testing code (it sorts an array of ints to the amount of ones in their binary representation using qsort (yes I know could have calculated the results more directly, but the point is the probleme I run into when trying to run free (here comment out in function ones))):
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25, 0, 15};
int * baseString(int u, int base);
int abs(int a);
int ones(int a);
int cmpfunc (const void * a, const void * b)
{
return ones(*(int*)a)>ones(*(int*)b);
}
int main()
{
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 7; n++ )
{
printf("%d ", values[n]);
}
qsort(values, 7, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 7; n++ )
{
printf("%d (Ones=%d) ", values[n], ones(values[n]));
}
printf("\n");
return(0);
}
int abs(int a){
return (a<0)? a*-1:a;
}
int* baseString(int u, int base){
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1;
if(base<2){
r[2]=-1;
return r;
}
int negativ=0;
if(u<0){
u=abs(u);
negativ=1;
}
int i=2;
do{
int ur=u%base;
r[i]=ur;
u/=base;
i++;
}while(u>0);
r[1]=i-1;
if(negativ){
r[1]=-r[1];
}
return r;
}
int ones(int a){
int* ai=baseString(a, 2);
int a1=1;
for(int i=2; i<abs(ai[1]); i++){
if(ai[i]==1){
a1++;
}
}
if(!a){
a1=0;
}
//free(ai);
return a1;
}
PS: I am quiet sure this thread is duplicate of some tread somewhere, but I didn't found it.
Part of your problem is actually quite simple.
In your baseString() function, the first three lines are
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1;
The malloc() dynamically allocates a single int, or an array with one element. The r[1] = 1 modifies the second element of that array which has one element.
The result of that is undefined behaviour. A common symptom of running off the end of an array like this is corrupting memory in your program, such as that used internally by malloc() and free() to keep track of allocated and released memory. Which would explain your problem.
Make sure you allocate the number of elements needed. For example, if 10 elements are needed, malloc(10*sizeof(int)). You need to work out the number needed, since dynamically arrays will not magically grow to get the number of elements needed.
I haven't look further, so there may be other problems. But this one is pretty glaring.
It is also a good idea to check that malloc() actually succeeds. It returns NULL if it fails.
The key problem here appears to an ABW (Array Bounds Write). In the baseString function, you are actually allocating memory which is equivalent to the size of 1 integer, but are trying to access it like an array in r[1],r[2], r[i] etc, which results in write to memory which technically doesn't belong to you.
The code snippet in your code corresponds to
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1; //ABW here
if(base<2){
r[2]=-1; //ABW here
return r;
}
do{
int ur=u%base;
r[i]=ur; //ABW here
u/=base;
i++;
}while(u>0);
This might lead to undefined behavior at any point of time in your code. In your case, it seems to be affecting free as the memory overwrite may have messed up with the internal book keeping data of malloc and free implementation.

Assign array without element by element copy?

I have a function which creates an array, of say, size 5.
Is it possible for the function to accept a pointer (or maybe it needs a pointer to a pointer?) and then point said pointer at an array, so that when the callee then looks at the pointer, it can see all values of the array.
Something along the lines of this (except this will not work):
#define LENGTH 5
void assignArray(int *pointer)
{
int arr[LENGTH] = {0,1,2,3,4};
// Point the pointer at the array, without manually copying each element
pointer = arr;
}
void main()
{
int *pointer;
pointer = malloc(sizeof(int) * LENGTH);
assignArray(pointer);
int i;
for (i = 0 ; i < LENGTH ; i++) printf("%d\n", pointer[i]);
}
C assign array without element by element copy
In C, arrays (compile-time allocated) cannot be assigned. You need to copy the elements from one array to another.
To avoid element-by-element copy, you can copy the whole array all at a time using library function.
I'm not very sure what you want to ask here, but it seems, you need to do memcpy() to achieve your goal.
If you have a secondary array arr to copy from, you can write
memcpy( pointer, arr, ( (sizeof arr[0]) * LENGTH ));
The code to do what you are describing might look like:
#define LENGTH 5
void assignArray(int **pp)
{
static int arr[LENGTH] = {0,1,2,3,4};
// Point the pointer at the array, without manually copying each element
*pp = arr;
}
int main()
{
int *pointer;
assignArray(&pointer);
for (int i = 0 ; i < LENGTH ; i++)
printf("%d\n", pointer[i]);
}
Note that one does not simply point *pp at a non-static local variable arr. That is because int arr[] = .... would go out of scope when assignArray returns.
If you want each call to assignArray to "return" a different array then of course you will have to allocate space and use memcpy each time you want to make a copy of the original array.
int arr[LENGTH] = {0,1,2,3,4}; will be stack allocated, so attempting to return the pointer to any of its elements will give you undefined behaviour as the whole thing will be out of scope when the function returns.
If you want to change what a pointer is pointing to then use 2 levels of indirection ** (i.e. pass a pointer to a pointer). You'll need to allocate the array arr on the heap using malloc or something similar.
As you are trying to do it, it is not possible due to the fact that your local arr is saved to the stack and is cleaned up after the function assignArry finished. As already mentioned you need to memcpy.
This answer will have two parts:
As mentioned in other answers, this is now how you're supposed to do it. A common construct in similar code is:
void assignArray(int *dest, size_t size)
{
int i;
// initialize with some data
for (i=0; i<size; i++)
dest[i] = i;
}
This way you're not wasting space and time with an intermediate buffer.
Second part of this answer is about wrapping arrays in a struct. It's a silly trick, that in a way achieves exactly what you asked, and also something that you probably don't want because of extra data copying.
Example code:
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 5
struct foo { int arr[LENGTH]; };
struct foo assignArray()
{
struct foo bar = { .arr = {0,1,2,3,4} };
/* return the array wrapper in struct on stack */
return bar;
}
int main()
{
struct foo *pointer;
pointer = malloc(sizeof(*pointer));
*pointer = assignArray(); /* this will copy the data, not adjust pointer location */
int i;
for (i = 0 ; i < LENGTH ; i++) printf("%d\n", pointer->arr[i]);
return 0;
}

Save pointer to array in struct

Save pointer to array in struct.
I would like to store the pointer to array of int into struct but I am having trouble.
Below my code with commentaries:
typedef struct _index {
int *data;
} Index;
void adder(struct _index *s){
int i;
int arr[maxint];
for(i=0; i<maxint; i++) {
arr[i] = i+42;
}
//i got a gibberish
//s->data = arr;
//works fine
s->data = (int *) malloc(maxint * sizeof(int));
s->data = memcpy(s->data, arr, maxint * sizeof(int));
)
int main() {
Index n;
int i;
//this method also works.
//int arr[maxint];
//for(i=0; i<maxint; i++) {
// arr[i] = i+42;
//
//}
//n.data = arr;
adder(&n);
for(i=0; i<maxint;i++) {
printf("%d-", n.data[i]);
}//testing
return 0;
}
when i make assignment, i got strange numbers:
117-118-119-120-12-0-22-2292964-0-2293008-127-0-129-130-131-0-0-0-0-0-0-138-0
but if i use malloc and memcpy all works fine
You got gibberish in your first case, because you tried to "return" the address of a local variable from a function through the pointer. Once the function finishes execution, the int arr[maxint]; won't be valid. In other words, after adder() finishes execution, int arr[maxint]; goes out of scope and it's lifetime is over. So, the (returned) pointer becomes invalid and using that further in the caller function will result in undefined behaviour.
Solution:
As you've done correctly, using dynamic memory.
use static variable (not a good approach, but possible).
In both the aforesaid approach, the lifetime of the variable ( static arr array/ malloc()ed memory) is not limited to function scope and thus, the pointer to the meory will be vaild in the caller function.
The array arr in the adder() function is on the stack and only exists as long as the code in that function is running. Once adder() returns that memory is re-used by the rest of the program and its content overwritten.
int arr[] is placed on the stack and gets removed from the stack when it goes out of scope. So you will point to garbage.
It works fine if you include it in your main because that way it hasn't gone out of scope yet.
Malloc works because you allocate memory and not just place it on the stack.

Return an array with all integers from a to b

The exercise says "Create a function with two parameters a and b which are integers and the function will return an array of integers with every number from a to b.
#include <stdio.h>
#include <stdlib.h>
void exc(int a, int b){
int i,k=0,d[k];
for(i=a;i<=b;i++){
d[k]=i;
k++;
printf("%d ",d[k]);
}
}
int main(void){
int c,d;
printf("Give first integer: ");
scanf("%d",&c);
printf("Give second integer: ");
scanf("%d",&d);
exc(c,d);
system("pause");
}
The problem is that if I put for example c=2 and d=5 the program returns something like 2088806975 16384 1 2293536 instead of 2 3 4 5. Where is the problem? Thanks
For starters
If your main() has return type int, don't forget to return a value from it!
int main(void)
{
/* code here */
return 0;
}
Problem 1
By
d[k]=i;
k++;
printf("%d ", d[k]);
I think you meant
d[k]=i;
printf("%d ", d[k]);
k++;
otherwise you're printing the "next" array element each time, which will be one-past-the-end of the array on the last loop iteration.
Problem 2
int i,k=0,d[k];
You make an array d of size k where k is 0. I think you intended for the array to automatically resize when you write k++, but this is not the case. The array is created with zero elements, and then that's its size for all time.
Your next instinct may be to create the array big enough in the first place:
int d[b-a+1];
Unfortunately, this is most likely wrong, too. It relies on a feature called Variable Length Arrays (or "VLAs"); although a GCC compiler extension (and, incidentally, C99) does allow this (and it's not clear whether you have that extension enabled and/or are allowed to use it in your homework — I will assume for this answer that you do not / are not), the language itself does not allow an array with a dynamic size.
What do I mean by dynamic size?
I mean that the variables a and b depend on user input: they are not known at compile-time. In general, the size of an array must be known at compile-time.
Note: If you use this, your code may compile without error, and your program may even appear to run and work correctly. However, you'd be relying on what's called "Undefined Behaviour", and your code could stop running or even crash at any time, due to any number of random, unpredictable factors. Even if it looks like it's okay, it's invalid. Don't do it!
Solution
Fortunately, there is a way to allocate a block of memory with the right size for your elements, when you don't know the elements until your program runs. It's called "dynamic allocation", and it involves a function call:
int *d = malloc(sizeof(int) * (b-a+1));
You can use the same syntax (d[k]) to access "elements" in this "array" or block of memory, but you must later manually free the memory:
free(d);
Possible problem 3
Your assignment says to return an array from the function, but you're not doing this. Instead, you're just creating, filling and printing the array all within the same function (which seems a bit pointless).
You can't actually return an array either, but since you're dynamically allocating the space for it, you have a pointer to work with. It's my opinion that your teacher may have wanted you to return a pointer to this array.
If so, the finished code looks a bit like this:
#include <stdio.h>
#include <stdlib.h>
int *exc(int a, int b)
{
int i, k = 0;
int *d = malloc(sizeof(int) * ((b-a)+1));
for (i=a; i<=b; i++) {
d[k]=i;
k++;
}
return d;
}
int main(void)
{
int a,b,i,*ar;
printf("Give first integer: ");
scanf("%d",&a);
printf("Give second integer: ");
scanf("%d",&b);
ar = exc(a,b);
for (i=0; i < (b-a+1); i++) {
printf("%d ", ar[i]);
}
free(ar);
system("pause");
return 0;
}
Disclaimer: I'm rusty on C, so the finished code might have a few syntax bugs.
Hope this helps!
The size of d is always 0. Since you are initializing it as d[k]. You should instead do something like d[b-a+1].
Update:
Furthermore, the order of your statements are wrong, see pmg's answer.
Update 2:
Your code doesn't actually return the array you are creating and it won't work unless you create the array on the heap (ie. using malloc / free).
The order of statements is not correct
d[k]=i; // d[0] = 42;
k++; // ...
printf("%d ",d[k]); // print d[1]
You need to allocate the memory for the array first, use malloc with the amount of integers you need to assign
Also, to be true to the problem statement, have the function return a pointer to the array so the main function can print it out instead of the exec function doing it directly.
Doing somebodys homework is always somewhat bad but obviously OP has no idea how to aproach this particular problem so here is a full example of dynamic memory allocation (overly commented).
#include <stdio.h>
#include <stdlib.h> /* required for malloc() and free() */
/* function that retuns a pointer to int type of data */
int *create_array(int a, int b)
{
int *array;
int array_size = b - a + 1; /* assuming that 'a' is always smaller than 'b' */
int i;
array = malloc( array_size * sizeof(int) ); /* allocate memory for the array */
if(array == NULL) exit(EXIT_FAILURE); /* bail out if allocation fails */
/* assign the values into array */
for(i = 0; i < array_size; ++i)
array[i] = a++;
/* return a pointer to our allocated array */
return array;
}
int main(void)
{
int *array;
int i, a = 42, b = 50;
/* and now we can call the function to create the array */
array = create_array(a, b);
/* print results */
for(i = 0; i < b - a + 1; ++i)
printf("%d\n", array[i]);
/* always remember to free the data after you are done with it */
free(array);
return 0;
}
You incorrectly declare d array in your code:
int d[k];
should be:
int d[b-a+1];
Edit::
Also, as others have posted, the statement order is wrong:
d[k]=i;
k++;
printf("%d ",d[k]);
should be:
d[k]=i;
printf("%d ",d[k]);
k++;
because otherwise you "lose" the first value when k==0.
You made an array of size zero and then started throwing data in without resizing the array. I'm a bit surprised that you aren't getting an error.
You're accessing data from memory outside the safety of defined data storage. It should be an error because the results are not defined. The data past the end of your array could be used for anything. And since your array is size zero, everything is past the end.
There are a couple problems. First, d is not returned from exc. Of course, you shouldn't just return it since it's allocated on the stack. Secondly, the printf is called after you increment k. That prints the next element in d, not the one whose value you just filled in. Finally, d doesn't have any space allocated for it, since k is always 0 when d is created.
It happens because you allocate memory for d on the stack. If you move the declaration of it outside the function, everything shoud be ok.

Resources