SMV
SMV

Reputation: 21

C.. Array... Problems with a course assignment

So I'm doing a course on C. One of the assignments is to look at and understand the code for sorting 5 grades(numbers). I copied the professor's code to MVS but it came up with errors. One of the issues I solved, as you can see by the comments in the code. But I don't understand how the professor managed to compile.

So my question is: how can the second error be solved?

int w[how_many];//error: expression must have a constant value.

Anyone care to help?

I'm using Visual studio. Tried "disable language ext.", rename source file from .cpp to .c and changed to "compile as C code (/TC)"

#include <stdio.h>
#define SIZE 5

void print_array(int how_many, int data[], const char* str)
{
    int i;
    printf("%s", str);

    for (i = 0; i < how_many; i++)
        printf("%d\t", data[i]);
}

void merge(int a[], int b[], int c[], int how_many)
{
    int i = 0, j = 0, k = 0;

    while (i < how_many && j < how_many)
        if (a[i] < b[j])
            c[k++] = a[i++];
        else
            c[k++] = b[j++];
    while (i < how_many)
        c[k++] = a[i++];
    while (j < how_many)
        c[k++] = b[j++];

}


void mergesort(int key[], int how_many) 
{
    
    int j, k;
    int w[how_many];//error: expression must have a constant value


    for (k = 1; k < how_many; k *= 2)
    {
        for (j = 0; j < how_many - k; j += 2 * k)
            merge(key + j, key + j + k, w + j, k);
        for (j = 0; j < how_many; j++)
            key[j] = w[j];
    }
}

int main(void)
{
    //const int SIZE = 5; // removed because of error and added #define SIZE 5
    int a[SIZE] = { 67, 82, 83, 88, 99 };// error: needs constant value, solved by adding #define SIZE 5
    
    print_array(SIZE, a, "My grades\n");
    printf("\n\n");
    mergesort(a, SIZE);
    print_array(SIZE, a, "Sorted grades\n");
    printf("\n\n");
    return 0;

}

Upvotes: 2

Views: 168

Answers (3)

ryyker
ryyker

Reputation: 23226

The solution is further down, but first, the failure here:

int w[how_many];//error: expression must have a constant value

is because the MSVC compiler does not support Variable-length Arrays (VLA). C99 and newer family of ANSI C compilers support VLA.

So, the solution here is to get a different compiler.

Note:

VS 2019 (16.8) will include /std:c11 and /std:c17 standards switches. See this blog post. Because the MSVC compiler does not support Variable-length Arrays (VLA) it does not claim C99 conformance. Note that these switches enable the new C99 preprocessor covered in this blog post

(From here: Is there any option to switch between C99 and C11 C standards in Visual Studio?)

So my question is: how can the second error be solved?

Before C99, C programmers that did not know the length of an array until run-time used dynamic memory allocation. In your example, this:

int w[how_many];

could be implemented as:

int *w = calloc(how_many * sizeof(*w));
if(w)
{
    memset(w, 0, how_many);//zero the new memory space. (VLA needs this too)
    //use variable in code
    ...
    free(w); //always free when done, (VLA does not require)
}

Edit to address OP later content added to post,

const int SIZE = 5;
int a[SIZE] = { 67, 82, 83, 88, 99 };

This is not a valid C VLA as it is not (and never has been ) legal to initialize a VLA in C. (It is however legal in C++)

This however is legal: (as 5 is a constant value.)

#define SIZE 5
int a[SIZE] = { 67, 82, 83, 88, 99 };

Upvotes: 2

That code is not proper standard C.

int main(void) {
    const int SIZE = 5;
    int a[SIZE] = { 67, 82, 83, 88, 99 };
}

is not valid C89, because it has a variable-length array. It is not valid C99, C11, or C18, because a variable-length array cannot be initialized.

It is valid C++ though, because an array whose dimensions are specified with a const int is of static type.

Additionally Clang C compiler compiles it, but Gnu C Compiler rightfully refuses to compile:

% gcc vla.c
vla.c: In function ‘main’:
vla.c:49:5: error: variable-sized object may not be initialized
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |     ^~~
vla.c:49:21: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                     ^~
vla.c:49:21: note: (near initialization for ‘a’)
vla.c:49:25: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                         ^~
vla.c:49:25: note: (near initialization for ‘a’)
vla.c:49:29: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                             ^~
vla.c:49:29: note: (near initialization for ‘a’)
vla.c:49:33: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                                 ^~
vla.c:49:33: note: (near initialization for ‘a’)
vla.c:49:37: warning: excess elements in array initializer
   49 |     int a[SIZE] = { 67, 82, 83, 88, 99 };
      |                                     ^~
vla.c:49:37: note: (near initialization for ‘a’)

% clang vla.c
% clang vla.c -pedantic
vla.c:49:11: warning: variable length array folded to constant array as an extension [-Wgnu-folding-constant]
    int a[SIZE] = { 67, 82, 83, 88, 99 };
          ^~~~
1 warning generated.

Suggested solution: get yourself a new professor.

Upvotes: 1

Vlad Feinstein
Vlad Feinstein

Reputation: 11311

Re:

So my question is: how can the second error be solved?

int w[how_many];//error: expression must have a constant value.

You can allocate memory for that array w like that:

int* w = malloc(how_many * sizeof(int));

Upvotes: 1

Related Questions