char name [1], но когда я ввожу 13 символов, на экране происходят странные вещи - PullRequest
0 голосов
/ 18 июня 2019

Это из книги "C Primer Plus" 4.2.2. Я использую MAC Xcode, чтобы попробовать пример кода самостоятельно.

Вот код:

#include <stdio.h>
#define PRAISE "You are an extraordinary being."
int main(void)
{
    char name[1];

    printf("What\'s your name?\n");
    scanf("%s", name);
    printf("Hello, %s. %s\n", name, PRAISE);

    return 0;
}

когда я ввожу «aaaaaaaaaaaaa», набирая 13 букв, на экране появляется:

libdyld.dylib`dyld3::MachOFile::forEachLoadCommand:
0x7fff697aa8a8 <+0>:   pushq  %rbp
0x7fff697aa8a9 <+1>:   movq   %rsp, %rbp
0x7fff697aa8ac <+4>:   pushq  %r15
0x7fff697aa8ae <+6>:   pushq  %r14
0x7fff697aa8b0 <+8>:   pushq  %r13
0x7fff697aa8b2 <+10>:  pushq  %r12
0x7fff697aa8b4 <+12>:  pushq  %rbx
0x7fff697aa8b5 <+13>:  subq   $0x28, %rsp
0x7fff697aa8b9 <+17>:  movb   $0x0, -0x29(%rbp)
0x7fff697aa8bd <+21>:  movq   %rdx, %r12
0x7fff697aa8c0 <+24>:  movq   %rsi, %rbx
0x7fff697aa8c3 <+27>:  movq   %rdi, %r15
->  0x7fff697aa8c6 <+30>:  movl   (%r15), %edx
0x7fff697aa8c9 <+33>:  cmpl   $0xfeedface, %edx         ; 
imm = 0xFEEDFACE 
0x7fff697aa8cf <+39>:  je     0x7fff697aa8e3            ; 
<+59>
0x7fff697aa8d1 <+41>:  cmpl   $0xfeedfacf, %edx         ; 
imm = 0xFEEDFACF 
Diagnostics::error(char const*, ...)
0x7fff697aa9a2 <+250>: addq   $0x10, %rsp
0x7fff697aa9a6 <+254>: addq   $0x28, %rsp
0x7fff697aa9aa <+258>: popq   %rbx
0x7fff697aa9ab <+259>: popq   %r12
0x7fff697aa9ad <+261>: popq   %r13
0x7fff697aa9af <+263>: popq   %r14
0x7fff697aa9b1 <+265>: popq   %r15
0x7fff697aa9b3 <+267>: popq   %rbp
0x7fff697aa9b4 <+268>: retq   

Для краткости я пропустил некоторые коды выше.

Если я ввожу больше букв, скажем 20 «a»,Он возвращает: ошибка: не удалось прочитать память для 0x7fff00616000

Если я изменю пятую строку на: имя символа [2];

и введу 14 символов, он возвращает тот же результат.

аналогично, если я изменю пятую строку на: char name [3];

и введу 15 символов, он возвращает тот же результат.

Я знаю, что это как-то связано сразмер aaray, однако, я понятия не имею, как число в скобках связано с соответствующим количеством вводимых символов.Может ли кто-нибудь объяснить это с деталями?

Ответы [ 2 ]

3 голосов
/ 18 июня 2019

char name[1]; достаточно большой, чтобы сохранить один символ.Если вы попытаетесь сохранить в нем более 1 символа, эти оставшиеся символы будут записаны в память после конца массива, что потенциально может перезаписать «важные» данные, что приведет к сбою (или, что еще хуже, повреждению данных, которые используются в других местах).

A string - это последовательность символьных значений, в том числе 0-значный терминатор.Если вы хотите сохранить N -характер строку , вам нужно выделить массив, который имеет по крайней мере N + 1 элемент в ширину.Итак, если вы хотите сохранить до 13-символьной строки в name, то вам нужно объявить ее как

char name[14]; // +1 to hold the string terminator

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

scanf( "%13s", name ); // at most 13 characters read into name

К сожалению, эту ширину поля нельзя указать с помощью аргумента (как это можно сделать в printf).Другой вариант - вообще не использовать scanf, а вместо него использовать fgets:

fgets( name, sizeof name, stdin );

fgets будет считывать не более sizeof name - 1 символов из stdin и записывать их вname, а затем добавьте терминатор 0 к концу name.sizeof name соответствует количеству байтов в name.

0 голосов
/ 19 июня 2019

странные вещи, происходящие на вашем экране, связаны с тем, что вы указали предел созданного массива '1' (т. Е. Имя [1]), и поэтому ввод будет содержать максимум один символ.Вы должны отредактировать ограничение массива до 15 или более (т. Е. Имя символа [15]), и поэтому пользовательский ввод увеличится до пятнадцати, что позволит вводить символы до 15. Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...