Имеет ли значение размер массива для пользовательской строки ввода в C? - PullRequest
1 голос
/ 15 октября 2019

Я пишу код для получения ввода пользователя с терминала в виде строки. Я читал в Интернете, что правильный способ создания строки в C - это использование массива символов. Мой вопрос: если я создаю экземпляр массива размером [10], это 10 индексов? 10 бит? 10 байт? См. Код ниже:

#include <stdio.h>

int main(int argc, char **argv){

    char str[10] = "Jessica";
    scanf("%s", &str);
    printf("%c\n", str[15]);

}

В этом примере "str" ​​инициализируется до размера 10, и я могу распечатать str [15], предполагая, что когда пользователь вводит строку, она доходит до тогоиндекс.

Мои вопросы:

  1. Увеличивается ли размер массива "str" ​​после получения значения из scanf?
  2. При каком количестве символов строки будет мойисходный массив переполнен? .

Ответы [ 3 ]

1 голос
/ 15 октября 2019

Одна из забавных маленьких слабостей C в том, что почти во всех случаях она не проверяет, чтобы убедиться, что вы не переполняете свои массивы.

Это ваша работачтобы убедиться, что у вас нет доступа за пределы ваших массивов, и если вы случайно это сделаете, может произойти почти все. (Формально это неопределенное поведение .)

Единственное, что не может произойти, это то, что вы получаете приятное сообщение об ошибке

Ошибка: вывести массив-пределенного доступа в строке 23

(Ну, теоретически, что может произойти, но на практике практически никакая реализация C не проверяет нарушения границ массива и не выдает подобные сообщения. )

См. Также этот ответ на аналогичный вопрос.

1 голос
/ 15 октября 2019

Массив объявляет заданное число того, что вы объявляете. Так что в случае:

char str[10]

Вы объявляете массив из десяти char s.

  1. Увеличивается ли размер массива "str" ​​послепринимая значение из scanf?

Нет, размер не меняется.

При каком количестве строковых символов мой исходный массив будет переполнен?

Массив из 10 char с будет содержать девять символов и нулевой терминатор. Таким образом, технически он ограничивает строку девятью символами.

printf("%c\n", str[15]);

Этот код ссылается на 16-й символ в вашем массиве. Поскольку ваш массив содержит только десять символов, вы обращаетесь к памяти вне массива. Кто-то может догадаться, владеет ли ваша программа этой памятью, и если да, то вы ссылаетесь на память, которая является частью другой переменной. Это рецепт катастрофы.

1 голос
/ 15 октября 2019

Когда вы объявляете массив char, как вы сделали:

char str[10] = "Jessica";

, вы сообщаете компилятору, что массив будет содержать до 10 значений типа char (вообще - может быть, даже всегда - это 8-битный символ). Когда вы затем попытаетесь получить доступ к «члену» этого массива с индексом, который выходит за пределы выделенного размера, вы получите то, что известно как Неопределенное поведение , что означает, что абсолютно всеможет произойти: ваша программа может произойти сбой;вы можете получить то, что выглядит как «разумное» значение;Вы можете обнаружить, что ваш жесткий диск полностью стерт! Поведение не определено. Итак, убедитесь, что вы придерживаетесь ограничений, установленных в объявлении: для str[n] в вашем случае поведение не определено, если n < 0 или n > 9 (индексы массива начинаются с нуля). Ваш код:

printf("%c\n", str[15]);

делает именно то, что я описал - он выходит за «границы» вашего массива str и, таким образом, вызывает описанное неопределенное поведение (UB).

Кроме того, ваш scanf("%s", &str); также может вызывать такой UB, если пользователь вводит строку символов длиннее 9 (один должен быть зарезервирован для завершающего символа nul)! Вы можете предотвратить это, указав функции scanf принимать максимальное количество символов:

scanf("%9s", str);

, где целое число, указанное после %, является максимально допустимой длиной ввода (все, что после этого будет проигнорировано)). Кроме того, так как str определен как массив, вам не нужен явный оператор "address of" (&) в scanf - он уже существует, так как ссылка на массив распадается на указатель!

Надеюсь, это поможет! Не стесняйтесь просить дальнейших разъяснений и / или объяснений.

...