C99 — Почему я не могу использовать массив символов переменной длины в Xcode 6?

Получил проект инструмента командной строки C, работающий в Xcode 6, и все отлично работает, кроме одной мелочи: я не могу понять, как присвоить значение массиву переменной длины! Например, рассмотрим следующий код:

#include <string.h>
int main()
{
    int len = 10;
    char str[len];
    strcpy(str, "hello");
    printf("%s", str);
}

Это компилируется нормально, но когда я его отлаживаю, массив никогда не назначается! Если я установлю точку останова в строке 7, нажму кнопку запуска и наведу указатель мыши на str, он просто отобразит это имя со стрелкой рядом с ним, которая при расширении ничего не показывает!

Поправьте меня, если я ошибаюсь, но я считаю, что это совершенно правильный код C99, который я пишу здесь... так что же дает?! Я пробовал компилятор GNU99 (по умолчанию) и компилятор C99, но безрезультатно.

МТС :-)

РЕДАКТИРОВАТЬ: ОК, я, кажется, запутался и, возможно, даже отправил несколько человек здесь (поскольку я получил по крайней мере 3 голоса против этого вопроса), поэтому позвольте мне немного прояснить ситуацию.

На самом деле я пишу приложение libcurl в Mac OS X Yosemite для загрузки файлов на веб-сервер через HTTP. В конце концов, я хочу иметь возможность ввести что-то вроде «загрузить [URL-адрес назначения] [файл или каталог 1] [файл или каталог 2] ... [файл или каталог N]» в Терминале, и моя программа автоматически загрузит эти файлы и каталоги в [адрес назначения]. Введенные пути могут быть относительно CWD или абсолютными.

Проблема существует в моей функции uploadDirectory, как показано здесь:

void uploadDirectory(CURL* hnd, struct curl_httppost* post,
    struct curl_httppost* postEnd, char* path, const char* url)
{
    DIR* dir = opendir(path);
    if (dir == NULL)
    {
        printf("\nopendir failed on path \"%s\"", path);
        perror(NULL);
    }
    else
    {
        struct dirent* file;
        while ((file = readdir(dir)) != NULL)
        {
            // skip the current directory and parent directory files
            if (!strcmp(file->d_name, ".") ||
                !strcmp(file->d_name, ".."))
                continue;

            if (file->d_type == DT_REG)
            {
                // file is an actual file; upload it
                // this is the offending code
                char filePath[strlen(path) + strlen(file->d_name) + 2];
                strcpy(filePath, path);
                strcat(filePath, "/");
                strcat(filePath, file->d_name);

                int res = uploadFile(hnd, post, postEnd, filePath, url);
                printf("%d", res);
            }
            if (file->d_type == DT_DIR)
            {
                // file is a directory; recurse over it
                // this section is omitted for brevity
            }
        }
        closedir(dir);
    }
}

Я знаю, что мог бы определить filePath с огромным постоянным размером, чтобы решить проблему, но насколько большим является слишком большой? Какова максимальная длина пути к файлу в OS X? И т. д., и т. д., поэтому я бы предпочел сделать его точно по размеру.

Если вы выдержали чрезмерную длину этого поста и добрались до него, спасибо за терпение! Сначала я пытался описать проблему как можно короче, но это, очевидно, не вызвало ничего, кроме путаницы, поэтому я прошу прощения за это :-)


person Kenny83    schedule 22.01.2015    source источник
comment
посмотрите на вывод ассемблера, ваша программа может быть оптимизирована до printf("hello");.   -  person mch    schedule 22.01.2015
comment
Вы подразумеваете, что этот код ничего не печатает?   -  person alk    schedule 22.01.2015
comment
Код работает, я запустил его и выдал: привет. Лучше всего добавить \n к функции printf: printf("output: '%s'\n", test);   -  person zaph    schedule 22.01.2015
comment
Вы #include <string.h>?   -  person Dmitri    schedule 22.01.2015
comment
Вау, вы все так быстро ответили, что у меня не было возможности исправить свои очевидные ошибки, LOL ... Теперь я соответствующим образом отредактировал свой вопрос. И, кстати, это просто пример кода, я на самом деле не пытаюсь вывести приветствие в консоль, лол... то, что я действительно пытаюсь сделать, намного сложнее и займет в 10 раз больше места и времени, чтобы написать это. все кончено... но суть проблемной области отражена здесь.   -  person Kenny83    schedule 22.01.2015
comment
Показанный код должен работать и добавить return 0 в конце main(). Я запустил его и получил правильный результат.   -  person Gopi    schedule 22.01.2015
comment
@Gopi: я знаю, что это должно работать, и я уверен, что это будет работать, если скомпилировано с помощью GCC и т. д., но у меня это не работает в Xcode, поэтому этот пост ... вы использовали Xcode проверить это? Если да, то какие параметры не по умолчанию мне нужно установить, чтобы это работало? Огромное спасибо :D   -  person Kenny83    schedule 22.01.2015
comment
Ваш 1-й фрагмент не соответствует прототипу printf(), поэтому вы должны включить <stdio.h>.   -  person alk    schedule 24.01.2015
comment
Также определение filePath и его использование совершенно правильно. Если код, как показано, дает сбой, основная причина, скорее всего, лежит в другом месте. Известно, что повреждение памяти вызывает несколько иррациональное поведение кода, поэтому вы можете захотеть отладить свою программу с помощью средства проверки памяти, такого как Valgrind (valgrind .org).   -  person alk    schedule 24.01.2015


Ответы (2)


int N;
scanf("%d",&N);

char a[N];

a — это VLA. Массив, показанный в вашем примере, не является VLA.

VLA поддерживаются в C99. Если вы не можете увидеть вывод, попробуйте

printf("%s\n", test);

Помимо этого, ваш код выглядит хорошо.

person Gopi    schedule 22.01.2015
comment
Спасибо, что так быстро ответили, но смотрите мой комментарий выше ;-) - person Kenny83; 22.01.2015
comment
У вас устаревший ответ. - person 2501; 22.01.2015
comment
@ 2501 Да, мне его удалить? - person Gopi; 22.01.2015
comment
Это не отвечает на вопрос и вводит в заблуждение. - person 2501; 22.01.2015

В итоге я провел некоторое исследование максимальной длины пути в OS X и наткнулся на эта запись stackoverflow.com, которая натолкнула меня на идею использовать <sys/syslimits.h> PATH_MAX определить. Это приемлемое решение, поскольку это определение всегда будет обновляться при необходимости.

person Kenny83    schedule 23.01.2015
comment
Это обходной путь, но не ответ на ваш вопрос, не так ли? - person alk; 24.01.2015