Программирование в C: ожидаемая ошибка константного выражения - PullRequest
1 голос
/ 05 февраля 2020

В настоящее время я пытаюсь скомпилировать калькулятор cr c, который я взял из github, и у меня возникают трудности при его компиляции в Visual Studio 2015. Я получаю постоянное выражение ожидаемой ошибки для строки:

char paths[strlen(src) + 1 + strlen(name) + 2 + 1];

Мысли о том, как я могу устранить ошибку?

static int create_source(char *src, char *name, FILE **head, FILE **code) {
    // for error return
    *head = NULL;
    *code = NULL;

    // create the src directory if it does not exist
    int ret = _mkdir(src, 0755);
    if (ret && errno != EEXIST)
        return 1;

    // construct the path for the source files, leaving suff pointing to the
    // position for the 'h' or 'c'.
    char paths[strlen(src) + 1 + strlen(name) + 2 + 1];
    char *suff = stpcpy(path, src);
    *suff++ = '/';
    suff = stpcpy(suff, name);
    *suff++ = '.';
    suff[1] = 0;

    // create header file
    *suff = 'h';
    *head = fopen(path, "wx");
    if (*head == NULL)
        return errno == EEXIST ? 2 : 1;

    // create code file
    *suff = 'c';
    *code = fopen(path, "wx");
    if (*code == NULL) {
        int err = errno;
        fclose(*head);
        *head = NULL;
        *suff = 'h';
        unlink(path);
        return err == EEXIST ? 2 : 1;
    }

    // all good -- return handles for header and code
    return 0;
}

Ответы [ 2 ]

3 голосов
/ 05 февраля 2020

Ваша непосредственная проблема - вы пытаетесь использовать VLA ( Array Variable Length Array ), введенный в стандарт с C99, с компилятором, который не поддерживает VLA. Без поддержки VLA массивы должны быть объявлены с целочисленной константой (а не просто const int). Начиная с C11, поддержка VLA является необязательной.

Чтобы решить вашу непосредственную проблему и обеспечить мобильность, просто выделите хранилище для paths вместо malloc. free памяти перед возвратом из вашей функции (либо при возврате ошибки, либо при успешном завершении)

Вы можете сделать что-то вроде:

size_t pathlen = strlen(src) + 1 + strlen(name) + 2 + 1;
char *paths = malloc (pathlen);     /* allocate storage for paths */
if (!paths) {                       /* validate EVERY allocation */
    perror ("malloc-paths");
    return 3;   /* or however you want to handle the error */ 
}
char *suff = stpcpy(path, src);

...

*head = fopen(path, "wx");
if (*head == NULL) {
    free (path);                    /* free paths */
    return errno == EEXIST ? 2 : 1;
}

...

if (*code == NULL) {
    int err = errno;
    free (path);                    /* free paths */
    fclose(*head);
    *head = NULL;
    *suff = 'h';
    unlink(path);
    return err == EEXIST ? 2 : 1;
}

free (path);                        /* free paths */
return 0;

Для этого есть небольшие издержки распределение и бесплатное, но оно незначительно в вашем случае, когда есть одно выделение и одно бесплатное.

0 голосов
/ 05 февраля 2020

В качестве простой альтернативы решению Дэвида, вы также можете использовать FILENAME_MAX ...

[...], который расширяется до целочисленного константного выражения, которое является размером, необходимым для массива char, достаточно большого, чтобы содержать самую длинную строку имени файла, которую реализация может быть открыта; (§7.21.1, ISO C11)

вот так

char paths[FILENAME_MAX];

Вы можете проверить, не превышаете ли вы этот размер.

...