tags:

views:

71

answers:

2

I am working on a small C application and I am capturing a value from the command line. I would like to capture the value and use it to initialize an array. Here is what I'm trying to do.

int main(int argc, char* argv[]) {
    int option = atoi(argv[2]);
    int values[option];
    ......
 }

I am getting a compilation because my option variable is not a const. Error: Error 2 error C2057: expected constant expression

Is there a way I can do this?

Thanks for your help!

+8  A: 

If the size is not known at compile-time, you need to allocate the memory dynamically, with malloc:

 int main(int argc, char* argv[]) {
    int option = atoi(argv[2]);
    int* values = malloc(option * sizeof(int));
    /* ...... */
    free(values); /* Deallocate the memory when you are done with it */
 }
Tyler McHenry
Thanks Tyler......when allocating memory using malloc why are you multiplying by sizeof()? Is the size of parameter the values type or the option type?
Buddy
`malloc` allocates in bytes. Multiplying by `sizeof(int)` converts the number of desired `int`s to the number of bytes required.
Adrian McCarthy
the questioners code compiles ok for me. is there any reason for not using the VLA feature introduced in C99?
starcorn
@klw Because if the OP's compiler was complaining about it, it clearly doesn't support C99. And the "C2057" error code suggests that it's the Microsoft compiler, which explicitly is *not* a C99 compiler.
Tyler McHenry
+1  A: 

If your compiler supports C99, then (if you don't mind living slightly dangerously, given that there is no check that argv[2] is defined or that the value in it can be converted to a sane positive integer), you can write:

#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
    int option = atoi(argv[2]);
    char *values[option];
    int i;
    int n = argc - 3;
    for (i = 0; i < n; i++)
        values[i] = argv[i+3];

    for (i = 0; i < n; i++)
        printf("values[%d] = %s\n", i, values[i]);
    return 0;
}

This compiles and runs, using the C99 VLA (variable-length array) feature. Note I changed the type of 'values' to a 'char *', mainly for laziness - to get something done.

The warning message looks like it comes from MSVC, and MSVC 2010 still does not support many of the extra features added to C99. For that environment, therefore, you will have to fall back onto memory allocation:

#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
    int option = atoi(argv[2]);
    char **values = malloc(option * sizeof(*values));
    int i;
    int n = argc - 3;
    for (i = 0; i < n; i++)
        values[i] = argv[i+3];

    for (i = 0; i < n; i++)
        printf("values[%d] = %s\n", i, values[i]);

    free(values);
    return 0;
}

Subtle point to note: the operand to 'sizeof' is '*values', which will remain correctly sized even if you change the type of 'values' from 'char **' back to 'int *' as in your outline. If I'd written 'sizeof(char *)', then you'd have to change two things - the declaration of 'values' and the type name in 'sizeof()'.

Jonathan Leffler
Since C99 supports variable declarations after other kinds of statements, couldn't you put in checks to ensure that argv[2] exists and has a sane numerical value?
Nathon
@Nathon: yes, I could. I didn't, and pointed out that I didn't. Doing it like that means that my code more closely resembles the question's code. Whether that was sufficiently important to outweigh the benefit of teaching 'check your inputs' is perhaps more debatable.
Jonathan Leffler
Sure, I saw that you pointed out that you didn't, I just wanted to make sure it was clear that it's possible to do, since it used to be illegal to check things like that before declaring stack variables.
Nathon
don't want to get side tracked but I just didn't put any checking in the sample code because I wanted to focus on the problem at hand with as minimal code as possible.
Buddy