Простой код внизу. Mac OS X 10.10.5, Xcode 7.2, C-файл. Если я ввожу 1, а затем qwert, я получаю 0 и обратно qwert. 1 и qwer дают 1 и qwer. 1 и например qwerty дает 121, а qwerty.

  • Что я пропустил - почему я могу записать более 4 символов (+ null) в переменную из 5 символов?
  • Почему затронуто целое число?
#include <stdio.h>

int main() {   
    int userInput;
    char q[5];

    printf("Hello\n");
    scanf("%d", &userInput);
    printf("%d\nAnd\n", userInput);
    scanf("%s", q);
    printf("\n");
    printf("%d\n%s", userInput, q);

    return 0;
}
0
Jackiie 23 Дек 2015 в 00:31

3 ответа

Лучший ответ

Что я пропустил - почему я могу записать более 4 символов (+ null) в переменную из 5 символов?

Ничто не мешает вам получить доступ к частям массива в c за пределами границ. Это скомпилирует:

char a[2];
a[10000] = 10;

Почему затронуто целое число?

Вы вызываете неопределенное поведение и, вероятно, является причиной того, что ваш int затронут. Вы можете узнать об этом больше, прочитав статью c arrays. Это происходит из-за того, что вы помещаете 5-символьную строку плюс нулевой завершающий символ (например, 6 chars) в пространство, предназначенное только для 5. Вы выходите за пределы своего массива.

В качестве дополнительного примечания, scanf("%s" не предлагает методов защиты от такого поведения. Если пользователь вводит слишком длинную строку, то это плохо. Вот почему вы должны защитить свой ввод, используя что-то вроде строки формата "%4s" или используя fgets:

fgets(q, sizeof q, stdin);

Это оба способа защитить свой ввод от ввода более 4 символов.

3
Fantastic Mr Fox 22 Дек 2015 в 21:53

Причина, по которой затрагивается int userInput, заключается в том, что вы пишете за концом массива char (q). Поскольку обе они являются переменными стека, похоже, что используемый вами компилятор выделяет память в стеке для локальных переменных в «обратном порядке», они «проталкиваются» в указанном порядке, поэтому первая локальная переменная перечисленные ниже в стеке. Итак, в вашем случае, когда вы пишете после конца q, вы записываете в пространство памяти, выделенное для userInput, поэтому это влияет.

0
DBug 22 Дек 2015 в 21:36

[Править] Пользователь / код может попытаться «записать более 4 символов (+ null) в 5-символьную переменную». C не указывает, что должно произойти, если код не предотвращает такое событие. C - это кодирование без страховочной сетки / обучающих колес.


scanf("%s", q); читает и сохраняет 5 символов "qwert" и также добавляет нулевой символ '\0'. @Weather Vane

Поскольку q[] имеет место только для 5 символов, возникает неопределенное поведение (UB). В случае OP кажется, что он перезаписал userInput.

Во избежание используйте ограничение ширины на "%s", как показано ниже. Он не будет занимать у пользователя более 4-х небелых пространств. К сожалению, лишний текст останется в stdin.

char q[5];
scanf("%4s", q);

Или, лучше, просмотрите fgets() на предмет чтения пользовательского ввода.

3
Community 23 Май 2017 в 11:44