1

I am required to pass a constant-size array to a function in C, but only use part of that array. Specifically, the following pseudo-code explains my situation:

void my_function(int arr_end,double arr[20]) {
    Create new array arr_new that contains elements 0 to arr_end or arr
    Use arr_new
}

So far, I tried to do the following:

void my_function(int arr_end,double arr[20]) {
    double arr_new[arr_end+1];
    int i;
    for(i=0;i<=arr_end;i++){
       arr_new[i] = arr[i];
    }
    // Now I can do what I want with arr_new
}

But I get the error: int arr_end expression must have a constant value . Here's a screenshot of the error in Visual Studio Community 2015: enter image description here

My problem is that arr_end is not constant (it means that at different times I want to extract a different portion of arr).

How can I achieve what I want (make arr_new contain a part of arr) using only for basic code and without malloc or anything like this? Thanks!

space_voyager
  • 1,984
  • 3
  • 20
  • 31
  • [Cannot reproduce.](http://ideone.com/cM8Zfv) Are you sure the error is thrown from this chunk of code? – cadaniluk Jul 24 '16 at 11:39
  • I think there's a conflict with datatypes, double arr_new and int arr_end – Fil Jul 24 '16 at 11:42
  • @Fil Array index should be non negative integers . `arr_new` and `arr_end` shouldn't be compared here. – ameyCU Jul 24 '16 at 11:43
  • 1
    Are you using a C99 compliant compiler? – Bob__ Jul 24 '16 at 11:43
  • I added a screenshot of the error. I'm not sure what compiler I'm using. – space_voyager Jul 24 '16 at 11:45
  • 1
    Ugh, yes, [Visual Studio isn't C99 compliant](http://stackoverflow.com/questions/9610747/which-c99-features-are-available-in-the-ms-visual-studio-compiler), so VLAs are not supported. Just replace the VLA with `malloc` and `free`. Look up how to do that, then post your new code if errors emerge. – cadaniluk Jul 24 '16 at 11:45
  • 1
    Well, you can declare another fixed size array (20 is the max, it seems) and use only `arr_end` elements of that... – Bob__ Jul 24 '16 at 11:51

5 Answers5

1

Dynamic size arrays are not allowed in older c versions, so you can either:

  1. change compilation flags to suit you and allow you to compile, if you are using an IDE this can be IDE dependent.

  2. allocate the array dynamically using malloc or a similar function like so:

void my_function(int arr_end,double arr[20])
{
    double *arr_new = malloc((arr_end+1) * sizeof(arr[0]));
    int i;
    for(i=0;i<=arr_end;i++){
       // do whatever you need
    }
}
  1. allocate an array of size 20 on the stack and just use only part of it(using the for loop) like so:
void my_function(int arr_end,double arr[20]) {
    double arr_new[20];
    int i;
    for(i=0;i<=arr_end;i++){
       //do whatever you need
    }
}

if you must send only the parts you need, method 2 is preferable.

Michael M.
  • 10,486
  • 9
  • 18
  • 34
monkeyStix
  • 620
  • 5
  • 10
  • For your 3rd solution, how do you use only part of an array? I need to pass it as a whole to another function that isn't mine, so how would I pass only part of an array to that function? – space_voyager Jul 24 '16 at 11:56
  • 1
    `allocate an array of size 20 on the heap` you mean _on the stack_, right? If the size is known, there's no point putting it on the heap (in this specific case, given that it's not large enough to smash the OP's stack, just for the pedants out there) – underscore_d Jul 24 '16 at 11:57
  • @space_voyager What is the signature of that function? Or better, what do you mean with _"I need to pass it as a whole"_ ? – Bob__ Jul 24 '16 at 12:06
  • @Bob__ I mean that I need to do something like `another_function(arr_new)` where `another_function` is that other function. I don't care about `arr_new`, I just need to pass a specific part of `arr` to `another_function`. – space_voyager Jul 24 '16 at 12:22
  • 1
    @space_voyager are you aware that arrays decay to pointers when passed as arguments to a function, right? So, usually, you have to pass the size of arrays in order to avoid out of bound access, unless the size is known as a global constant. – Bob__ Jul 24 '16 at 12:30
1

First in the my_function arguments you are declaring that you are receiving an array with a size of 20 (double arr[20]), since arrays cannot be passed by value it gets converted to double* arr (see this) without knowing how many elements arr has, so you should be carefully or you will get a segfault. A recommended approach would be to change double arr[20] to double* arr and add another argument for the size of arr. Example:

void my_function(const size_t arr_end, double* arr, const size_t arr_size) {
    ...
}

Second you are trying to use VLAs with MSVC which only supports C90 and VLAs we're added on C99 so you will need to allocate memory manually with malloc and free it with free when you finished using it.

Now here is the code fixed:

void my_function(size_t arr_end, double* arr, size_t arr_size) {
    double* arr_new = NULL;

    // Allocate enough memory to hold the array
    arr_new = malloc((arr_end + 1) * sizeof(double));

    // Copy arr elements to arr_new
    for(int i = 0; i <= arr_end; i++){
       arr_new[i] = arr[i];
    }

    // Now you can do what you want with arr_new

    // When you finished using it.
    free(arr_new);
}
Community
  • 1
  • 1
0

As far as I know the problem is that when you are creating dynamic arrays then the only way is using malloc to allocate space. Then you assign it to an array as in double arr_new[arr_end+1];. arr_end can only be an explicit value, e.g., 1, 2, or 3, not a variable like arr_end. It should be something like this double arr_new[5];

cadaniluk
  • 15,027
  • 2
  • 39
  • 67
henrybbosa
  • 1,139
  • 13
  • 28
  • 1
    That is true for old versions of C (and all versions of C++). But the OP can compile under a newer version and gain the ability to use such Variable-Length Arrays. See the comments to the OP. – underscore_d Jul 24 '16 at 11:48
  • @underscore_d [I don't think so.](http://stackoverflow.com/questions/9610747/which-c99-features-are-available-in-the-ms-visual-studio-compiler) – cadaniluk Jul 24 '16 at 11:48
  • @Downvoter "compile under a new version" of C, i.e. with a compiler that supports such. What MS doesn't support is such a long list that it's wholly uninteresting to me. But I was referring to your comment on the OP that helpfully makes this clear. (great name, btw) – underscore_d Jul 24 '16 at 11:49
  • @underscore_d How do you know the OP can "compile under a new version"? – cadaniluk Jul 24 '16 at 11:51
  • @Downvoter Must I word everything completely literally, with intimate knowledge of each person's literal situation? Obviously "can" implies _here is what the language can do, if it's logistically possible for you_. What else have you got? Let's try and get all the pedantry out of the way at once. – underscore_d Jul 24 '16 at 11:53
0

Use dynamic allocation. Code:

void foo(int end, double arr[20]){
    double* newArr = malloc((end + 1) * sizeof(double));
    //now you can use newArr like a normal array
    //Copy like this
    for(int i = 0; i < end; i++){
        newArr[i] = arr[i];
    }
}
0

Apparently, the problem lies with Visual Studio. The concept of Variable Length Arrays (VLAs) is of the C99 standard, whereas Visual Studio seems to support only C90.

They do seem have a workaround for that however, you can find it here: https://msdn.microsoft.com/en-us/library/zb1574zs(v=vs.140).aspx

Magnus
  • 59
  • 6
  • That page makes no sense. "Here's how you can use VLAs [...] VLAs are not currently supported." Which is it? – underscore_d Jul 24 '16 at 12:00
  • The code section below it, the #pragma line. Can't really help it. Blame it on MS for not supporting newer standards. – Magnus Jul 24 '16 at 12:01
  • Yes, I did in fact read the whole thing, but it still doesn't make sense. It first says VLAs aren't supported, then declares one, and only then does some threading-related stuff with it, which seems to be orthogonal. All the other questions I've found about this imply it can't be done. So, if you've discovered otherwise, it would be worth expanding your answer to explain why this workaround works. At the moment, their example looks unrelated. – underscore_d Jul 24 '16 at 12:03
  • I agree, it makes no sense. Its more of a hack to cover up the lack of support. Perhaps you could switch to GCC for the new features? – Magnus Jul 24 '16 at 12:07
  • If it is a hack or cover-up, how does it work? There's no explanation there, and I can't find any relevant search results identifying that `firstprivate` directive as some kind of workaround that makes VLAs work, so I feel obliged to conclude that the page is a non sequitur. Anyway, I'm not the OP, and I already use GCC and highly recommend it. – underscore_d Jul 24 '16 at 12:11