【问题标题】:Why string is taking larger string than size in C为什么字符串在 C 中占用的字符串大于大小
【发布时间】:2021-12-31 05:47:13
【问题描述】:

我已将字符串 word 的大小设置为 5。我正在使用 scanf() 输入,格式说明符是 %s。虽然字符串的大小为 5,但如果我输入的字符串大于长度 5,它也会占用整个输入。为什么会这样?

这是我的 C 程序:

#include <stdio.h>
#include <string.h>

int main() {
  char word[5];
  printf("Enter word: ");
  scanf("%s", word);
  printf("Word: %s\n", word);
  strlwr(word);
  printf("To Lower: %s\n", word);
  return 0;
}

如果我输入长度为 10 的 AbcDEfghij,但它会使用它并正确打印完整的字符串。我怎样才能防止这种情况?我不想接受大于大小的输入。

【问题讨论】:

  • “我怎样才能防止这种情况发生?” --> scanf("%4s", word);
  • 这个小程序可能会打印出正确的结果,这取决于编译器和系统,但你可能会注意到最后的一个小故障,并且随着程序变得越来越大,它变得越来越糟糕,变得非常困难跟踪错误。

标签: c string


【解决方案1】:

C 不对数组执行边界检查。这是让它快速的部分原因。然而,这也意味着它允许你做一些你不应该喜欢写超出数组边界的事情。当你这样做时,你会触发undefined behavior

当您的程序有未定义的行为时,它可能会崩溃,它可能会给出奇怪的结果,或者它可能(如您的情况)似乎正常工作。更糟糕的是,看似无关的更改(例如添加未使用的局部变量或添加printf 调用调试)可能会改变未定义行为的表现方式。

总而言之,语言相信你不会做你不应该做的事情。

【讨论】:

  • 如果字符串可以接受比定义更大的输入大小,那么为什么我们在初始化时必须提及大小。
  • @SatyajitRoy 所有数组都必须具有定义的大小。作为程序员,你有责任确保你没有超过这个大小限制。
  • @SatyajitRoy 你错过了重点。字符串不能“接受比定义更大的输入”。这样做会导致未定义的行为,从而使您的程序无效。为了使您的程序得到良好定义,即有效,您不得访问超过其大小的字符串和数组。你不能这样做!
【解决方案2】:

您看到缓冲区溢出。在 C 中,字符串表示为一个字节字符的数组,以 NULL 字符结尾。 scanf 不知道您的缓冲区有多大,并且很乐意将任何输入复制到其中。此漏洞会导致一类称为buffer overflow attacks 的安全漏洞。这可能会导致有趣的结果,例如 this example,它被设置为以 123456 作为输入,你将溢出你的字符数组,它应该输出值 54,对应于 6 的 Ascii 代码。

#include <stdio.h>
#include <stdint.h>

struct overflow_test{
    char buffer[5];
    uint8_t number;
};

int main()
{
    struct overflow_test s;
    s.number=6;
    printf("%d\n", s.number);
    printf("\n");
    scanf("%s", &s.buffer);
    printf("%d\n", s.number);
    return 0;
}

您有责任确保接收的字符数不超过缓冲区的容量。为避免此问题,您可以改用 fgets 之类的函数,它可以接收最大数量的字符,这样您就不会溢出缓冲区。

【讨论】:

    猜你喜欢
    • 2022-11-30
    • 1970-01-01
    • 2017-01-14
    • 2022-12-17
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    相关资源
    最近更新 更多