R_C R_C - 2 months ago 12
C Question

C - Returning array not working

I am trying to obtain a long number, count how many digits it is, then take the 2nd last digit of that number and multiply it by 2, then iterate through the rest of the number multiplying each 2nd and then adding it to an array. It is the credit card problem set from cs50 if you guys know what I'm talking about.

When I make the program it throws back this error:

error: format specifies type 'long' but the argument has type '<dependent type>' [-Werror,-Wformat]
credit.c:22:21: error: use of undeclared identifier 'array'
printf("%ld\n", array);
^
credit.c:40:8: error: incompatible pointer to integer conversion returning 'long [nDigits]' from a function with result type 'long' [-Werror,-Wint-conversion]
return array;
^~~~~
3 errors generated.
make: *** [credit] Error 1


Code:

#include <cs50.h>
#include <stdio.h>
#include <math.h>

long find_2ndlast_nums(long x);

int main(void)
{
long n;
long nDigits;
do
{
n = get_long_long("Please enter your credit card number:\n");
nDigits = floor(log10(labs(n))) + 1;
}
while (nDigits < 13 || nDigits > 16);

find_2ndlast_nums(n);

printf("%ld\n", array);
}

long find_2ndlast_nums(long x)
{
long nDigits = floor(log10(labs(x))) + 1;
long array[nDigits];

for (int y = 1; y < nDigits; y += 2)
{
x = (fmod((floor(x / 10 ^ y)), 10)) * 2;
array[nDigits - y] = x;
}
return array;
}

Answer Source

There are two problems here:

  1. When you declare an array in C with type[count], it's allocated on the stack. As soon as your function returns, everything on the current stack frame will become invalid, so you can't return a stack-allocated array like this.

  2. Even if you could return that array, you declared the function as returning a long, not a pointer to long, so the signature's incorrect.

What I'd do is to allocate memory for the array on the heap, using malloc. Declare the function as returning a pointer, and then return the pointer to the array. Unfortunately, the calling function will have to remember to free the pointer afterward or you'll have a memory leak, but this is just one of the things that goes with the territory when you're using C.

So, something like this:

long *myFunc() {
    long *array = malloc(count * sizeof(long));

    // populate the array

    return array;
}

And in the client:

long *array = myFunc();

// do something with array, and when you're done:

free(array);

Alternatively, if you can know ahead of time what the maximum size of the array will be, you can have the function populate an already-allocated array. This has the advantage of making the code cleaner by letting your malloc and free occur in the same scope. Also, if the array doesn't need to leave the calling function, the calling function can allocate the array on the stack and pass it in, thus obviating the need for malloc and free altogether.

void populateArray(long *array, size_t arraySize) {
    // populate array. Don't write more than arraySize objects
    // or you'll cause a buffer overflow.
}