【问题标题】:Does specifying array size for a user input string in C matter?在 C 中为用户输入字符串指定数组大小是否重要?
【发布时间】:2019-10-15 17:20:34
【问题描述】:

我正在编写一个代码,以将来自终端的用户输入作为字符串获取。我在网上读到,在 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. 从 scanf 取值后,“str”数组的大小是否增加?
  2. 我的原始数组会溢出多少字符串字符? .

【问题讨论】:

  • 您正在使用 printf("%c\n", str[15]); 调用 未定义的行为 - 在这种情况下任何事情都可能发生
  • No out of bounds error的可能重复
  • 共有 10 个索引,从 09。根据定义,字符串是元素值为 '\0'(或简称为 0)的数组,因此您的数组最多可以包含 9 个字符(0 到 9 个字符 + 0 元素)
  • UB 抬起丑陋脑袋的方法之一就是做你想做的事……除了满月的星期三
  • C 是一种非常有效的工具,但并不安全。就像电锯一样。你没有错误就是因为这个。

标签: c arrays string scanf


【解决方案1】:

当您声明一个 char 数组时:

char str[10] = "Jessica";

然后您告诉编译器该数组将容纳 10 类型的 char 值(通常 - 甚至可能总是 - 这是一个 8 位字符)。然后,当您尝试使用超出分配大小的索引访问该数组的“成员”时,您将获得所谓的 Undefined Behaviour,这意味着绝对可能发生任何事情:您的程序可能会崩溃;您可能会得到看起来像“明智”的价值;你可能会发现你的硬盘被完全擦除了!行为未定义。因此,请确保您遵守您在声明中设置的限制:对于您的情况,对于 str[n],如果 n &lt; 0n &gt; 9(数组索引从零开始),则行为未定义。你的代码:

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

正如我所描述的那样 - 它超出了您的 str 数组的“界限”,因此将导致所描述的未定义行为 (UB)。

另外,您的scanf("%s", &amp;str); 也可能导致这样的UB,如果用户输入的字符串长度超过9(必须为终止nul 字符保留一个字符)!您可以通过告诉scanf 函数接受最大字符数来防止这种情况:

scanf("%9s", str);

% 之后给出的整数是允许的最大输入长度(此后的任何内容都将被忽略)。此外,由于str 被定义为一个数组,因此您不需要scanf 中的显式“地址”运算符(&amp;) - 它已经存在,因为数组引用衰减为指针!

希望这会有所帮助!随时要求进一步澄清和/或解释。

【讨论】:

  • 这很有帮助。谢谢你。所以基本上它可以工作,但它不是最安全/可靠的实现。为了清楚起见,我还有两个问题: 1. 如果我接受用户输入,是否有任何方法可以使我的数组与他们的输入大小相同而不首先声明数组的大小? 2. C 字符数组的最大大小是多少?
  • @KaasimShaikh 永远不要认为它可能有效!没用,就这么简单。在其他方面,将数组大小声明为用户希望字符串的最大(合理)长度! C 标准没有定义最大大小(我认为 - 但也许确实如此),但是如果您尝试将其声明为(例如)60 亿,您的编译器/构建器和/或操作系统可能会失败。跨度>
【解决方案2】:

C 的一个有趣的小缺点是,在几乎所有情况下,它都会检查以确保你的数组没有溢出。

您的工作是确保您不会访问数组边界之外的内容,如果您不小心这样做了,几乎任何事情都可能发生。 (正式地说,它是未定义的行为。)

唯一不会发生的事情是您会收到一条不错的错误消息

错误:第 23 行的数组越界访问

(嗯,理论上可能会发生,但实际上,几乎没有 C 实现检查数组边界违规或发出类似的消息。)

关于类似问题,另请参阅 this answer

【讨论】:

    【解决方案3】:

    一个数组声明了你声明的给定数量。所以在这种情况下:

    char str[10]
    

    您正在声明一个包含 10 个 chars 的数组。

    1. 从 scanf 取值后,“str”数组的大小是否增加?

    不,大小不变。

    1. 我的原始数组会溢出多少字符串字符?

    10 个chars 的数组将包含九个字符和空终止符。因此,从技术上讲,它将字符串限制为九个字符。

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

    此代码引用数组中的第 16 个字符。因为您的数组只包含十个字符,所以您正在访问数组之外​​的内存。任何人都可以猜测您的程序是否甚至拥有该内存,如果拥有,那么您引用的内存是另一个变量的一部分。这是灾难的根源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-02
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2016-02-10
      • 1970-01-01
      相关资源
      最近更新 更多