1

New to C here and would appreciate if I could get some pointers.

I'm trying to initialise an array inside an if statement, and then print the values of the array externally - but I know the scope will be lost after the if block ends. I've tried creating the array with pointers. The reason I'm doing it inside the if statement is because the size of the array depends on a value calculated during runtime.

E.g.:

void createArray() {

    int userInput;
    printf("%s\n", "Please enter a value:");
    scanf("%d\n", userInput);

    if (userInput > 10) {
       int array[userInput];
    }

    int i;
    for (i = 0; i < userInput; i++) {
       array[i] = i;
    }
}

int i;
for (i = 0; i < sizeof(array)/sizeof(array[0]); i++) {
  printf("%d\n", array[i]);
}

However because the array is declared inside a method, I obviously lose scope of it when it comes to the final for loop to print - thus an error occurs. I've tried creating a pointer variable int *array as a global variable, and inside the if statement, just staying array = int[10] but obviously this won't work.

This isn't my exact code, I've recreated a minimal example that shows my error so some syntax may be wrong here - apologies for that.

Any help would be appreciated.

  • Could you give me an example please? Would be appreciated :) –  Oct 06 '15 at 16:46
  • call scanf("%d\n", &userInput); instead of scanf("%d\n", userInput); using malloc is standard practice, but if you have asked how to use outside the if block, then you can do something like int *ptr = NULL; in the beginning and then ptr=array after int array[userInput];, and then use ptr wherever you want to use array. But the scope of ptr will the function only and you cant use the ptr outside function – Ritesh Oct 06 '15 at 16:56

3 Answers3

3

One question you have to consider in your code is what happens if userInput is less than or equal to 10? You iterate over userInput elements of an array that was not declared.

One simple way of handling this is to make a large array at the beginning of your function and then use just the first userInput elements of it. This approach has obviously its limitations (e.g. userInput can't be larger than the size of the array, and you should make sure it won't be, otherwise bad things may happen), but is simple.

Another approach involves using dynamic memory allocation. This is done by using the malloc function:

int *array = malloc(100 * sizeof(int));

The code above allocates memory for 100 ints, basically creating an array of 100 elements. Then, you can use the array as usual. But, make sure you free it after you're done:

free(array);

Note that using this approach you'd need to declare the pointer first:

int *array;
if (userInput > 10) {
   array = malloc(userInput * sizeof(int));
}

Below you can find a small proof of concept program. Note that instead of a global variable, the pointer value can be returned from the alloc function.

#include <stdio.h>
#include <stdlib.h>

int *arr;

void alloc() {
    arr = malloc(10 * sizeof(int));
}

void assign() {
    for (int i = 0; i < 10; i++)
        arr[i] = i + i;
}

void print() {
    for (int i = 0; i < 10; i++)
        printf("%d\n", arr[i]);
}


int main(int argc, char *argv[])
{
    alloc();
    assign();
    print();
    free(arr);
    return 0;
}
Paul92
  • 8,827
  • 1
  • 23
  • 37
  • Thanks for the reply. If I want to use the array in other functions also, should I declare `int *array` as a global variable? –  Oct 06 '15 at 17:02
  • Yes. Or, you can return it. However, don't forget the free() :D – Paul92 Oct 06 '15 at 17:04
  • 1
    @F.Tahir: Although it might feeling convenient, easier to define `array` globally in the beginning, in the long run you do not want to do this, but definitely return it from the function. – alk Oct 06 '15 at 17:07
  • I've taken your suggestion and done the following: `int *array` as a global variable, and then inside my function, `array = malloc(userInput * sizeof(int))`. When attempting to store values in the array using for (i = 0; i < userInput; i++) { array[i] = i; }`, it throws the error: `subscripted value is neither array nor pointer nor vector` –  Oct 06 '15 at 17:07
  • For an example see this answer http://stackoverflow.com/a/13208829/694576 to a similar question. – alk Oct 06 '15 at 17:09
  • @alk your example uses a int**, which may be confusing to say the least. – Paul92 Oct 06 '15 at 17:18
  • I have updated my answer with a proof of concept which I hope makes it clear. It's hard to see why you get that error without a code sample. – Paul92 Oct 06 '15 at 17:18
  • @Paul92: That's way to go. Imagine you need to allocate two arrays, then you are lost with just one value to return. Also it is a good idea to reserve to return value of a function to indicate success or failure. And no, using `NULL` as a return value is error prone. – alk Oct 06 '15 at 17:24
  • @alk the OP was not concerned with allocating multiple arrays. Also, why do you think using NULL is error prone? – Paul92 Oct 06 '15 at 17:31
  • It's not `NULL` which is error prone, but returning a pointer value. – alk Oct 06 '15 at 17:32
3

This allocates an array of int to the pointer intary. The pointer may be passed to other functions from main(). In main, userInput stores the number of int allocated.

#include <stdio.h>
#include <stdlib.h>

int *createArray( int *userInput);

int main( int argc, char *argv[])
{

    int i;
    int userInput = 0;
    int *intary = NULL;

    if ( ( intary = createArray ( &userInput)) != NULL ) {

        for (i = 0; i < userInput; i++) {
            intary[i] = i;
            printf ( "%d\n", intary[i]);
        }

        free ( intary);
    }
    return 0;
}

int *createArray( int *userInput) {

    int *array = NULL;

    printf("%s\n", "Please enter a value:");
    scanf("%d", userInput);

    if ( *userInput > 10) {
        if ( ( array = malloc ( *userInput * sizeof ( int))) == NULL) {
            printf ( "could not allocate memory\n");
            *userInput = 0;
            return NULL;
        }
    }
    else {
        *userInput = 0;
        return NULL;
    }

    return array;
}
user3121023
  • 8,181
  • 5
  • 18
  • 16
1

You don't need some pointers, just one, (int* arr) and malloc(),a dynamic memory allocation function.

Note: You shouldn't use "array" as a variable name as it may create problems. So we'll name our variable arr.

If you're unfamiliar with it, i will explain the code too.

  1. First add #include <stdlib.h> header file, which contains malloc().

  2. Then declare a pointer of type int int* arr, we have named it arr in the createArray() scope.

  3. We'll allocate the space required in the if condition with malloc() function, like :

    void createArray() {
        int userInput;
    
        int* arr; // declare arr pointer
    
        printf("%s\n", "Please enter a value:");
        scanf("%d\n", userInput);
    
       if (userInput > 10) {
    
           arr = (int*) malloc ( userInput * sizeof(int) ); // explained below
       }
    
       int i;
       for (i = 0; i < userInput; i++) {
           arr[i] = i;
       }
    }
    
    free(arr) // don't forget to free after using
    

[NOTE] This code is untested.

arr = (int*) malloc ( userInput * sizeof(int) );
This line may seem cryptic at first, but what it does is pretty simple , it allocates some memory dynamically on the heap.
The size of this memory is given by 'userInput * sizeof(int)', sizeof() function specifies the size of int on the given machine multiplied by userInput by the user,
Then, it is typecasted to int* type so that we can store the address in our int* type pointer arr.

[UPDATE] you can use arr = malloc ( userInput * sizeof(int) ); instead as suggested in comments, here is why Do I cast the result of malloc?

Community
  • 1
  • 1
  • 3
    This will cause an error when userInput is less than 10. Also, a lot of people on SO will tell you not to cast the return value of `malloc`. – E. Moffat Oct 06 '15 at 17:09
  • And `array` is a perfectly valid name. What do you think it collides with? It is unlikely this will be translataed with a Pascal compiler. – too honest for this site Oct 06 '15 at 17:13
  • Also there is no need to use `malloc`. If `array` is only used in the function and not too big, a VLA is fine. You code OTOH is open to undefined behaviour, the function signature will generate a warning on a recent C compiler (i.e. since C99) and `free` is actually called outside a function body (OP was wrong here, too). Oh, and: Do not cast the result of `malloc` & friends in C! – too honest for this site Oct 06 '15 at 17:17
  • @E.Moffat yes it is not the complete code, like the OP asked for, these are just some pointers on how he can approach the problem. – Abhishek Arora Oct 06 '15 at 17:19
  • Posting broken code is not a good idea, at least if not marking it as such **explicitly**. – alk Oct 06 '15 at 17:46
  • @alk The OP did not provide full code so i just edited into his code to make him understand a way he could do it. But thanks for your comment, i have added a note. – Abhishek Arora Oct 08 '15 at 13:57