Как компилятор выделяет память для массива строк в C? - PullRequest
0 голосов
/ 06 марта 2019

Я набрал этот блок кода для назначения:

char *tokens[10];

void parse(char* input);

void main(void) 
{
    char input[] = "Parse this please.";
    parse(input);

    for(int i = 2; i >= 0; i--) {
        printf("%s ", tokens[i]);
    }
}

void parse(char* input)
{
    int i = 0;
    tokens[i] = strtok(input, " ");

    while(tokens[i] != NULL) {
        i++;
        tokens[i] = strtok(NULL, " ");
    }
}

Но, глядя на это, я не уверен, как работает распределение памяти.Насколько я знаю, я не определял длину отдельных строк, а сколько строк содержится в токенах массива строк (10).У меня есть это задом наперед?Если нет, то компилирует ли компилятор длину каждой строки динамически?Нуждается в пояснениях.

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

strtok плохой гражданин.

Во-первых, он сохраняет состояние, которое вы неявно использовали при вызове strtok(NULL,...) - это состояние сохраняется в частной памяти библиотеки Standard C, что означает, что только однопоточные программы могут использовать strtok , Обратите внимание, что в некоторых библиотеках существует реентерабельная версия с именем strtok_r.

Для другого и для ответа на ваш вопрос strtok изменяет свой ввод. Он не выделяет место для строк; он записывает NUL-символы вместо разделителя во входной строке и возвращает указатель на входную строку.

Вы правы, что strtok может вернуть более 10 результатов. Вы должны проверить это в своем коде, чтобы не писать после конца tokens. Надежная программа либо установит верхний предел, например, 10, и проверит его, сообщит об ошибке, если она превышена, либо динамически выделит массив tokens с помощью malloc, и realloc, если получит слишком много большой. Тогда ошибка возникает, когда вам не хватает памяти.

Обратите внимание, что вы также можете обойти проблему strtok изменения входной строки с помощью strdup ing перед передачей ее strtok. Затем вам нужно будет освободить новую строку после того, как она и tokens, которые указывают на нее, выйдут за пределы области.

1 голос
/ 06 марта 2019

tokens - это массив указателей.

Различие между строками и указателями, если часто нечеткое.В некоторых ситуациях строки лучше воспринимать как массивы, в других - как указатели.

В любом случае ... в вашем примере input - это массив, а tokens - это массив указателей на место внутри input.

Данные внутри input меняются при каждом вызове на strtok()

Итак, шаг за шагом

// input[] = "foo bar baz";
tokens[0] = strtok(input, " ");
// input[] = "foo\0bar baz";
//            ^-- tokens[0] points here
tokens[1] = strtok(NULL, " ");
// input[] = "foo\0bar\0baz";
//                 ^-- tokens[1] points here
tokens[2] = strtok(NULL, " ");
// input[] = "foo\0bar\0baz";
//                      ^-- tokens[2] points here
// next strtok returns NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...