char name[1],但是当我输入 13 个字符时,屏幕上会发生奇怪的事情

标签 c arrays char

出自《C Primer Plus》一书 4.2.2 String 我正在使用 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;
}

当我输入“aaaaaaaaaaaaaa”,共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个字符,返回相同的结果。

同样, 如果我将第五行更改为: 字符名称[3];

并输入15个字符,返回相同的结果。

我知道这与aaray的大小有关,但是,我不知道括号中的数字是如何连接到相应的输入字符数的。谁能详细解释一下吗?

最佳答案

char name[1]; 仅足以存储单个字符。如果您尝试向其中存储超过 1 个字符,则剩余的字符将在数组末尾写入内存,这可能会覆盖“重要”数据,从而导致崩溃(或更糟糕的是,会损坏其他地方使用的数据)。

字符串是包含 0 值终止符的字符值序列。如果要存储 N 字符字符串,则需要分配一个至少 N+ 的数组1 个元素宽。因此,如果您想在name中存储最多13个字符的字符串,那么您需要将其声明为

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 将从 stdin 读取不超过 sizeof name - 1 个字符并将其写入 name,然后将 0 终止符添加到 name 的末尾。 sizeof name 计算出name 中的字节数。

关于char name[1],但是当我输入 13 个字符时,屏幕上会发生奇怪的事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56652585/

相关文章:

c - 编写程序输出24小时制数字时钟显示的所有回文时间(如13 :31)

c - 使用 ncurses 从文件打印 ascii 艺术效果很奇怪

c - 打印结构显示垃圾

php - 通知 : Array to string conversion with date

c++ - 动态创建二维数组的函数

c++ - 如何从 char16_t 字符串文字中读取 double 值?

c - 在C中对char指针数组进行排序

c++ - 将数组中的所有元素与另一个数组进行比较

javascript - 无法使用 Javascript/Jquery 从数组中删除行

objective-c - 将 char 数组保存到 iPhone