【问题标题】:String is longer than expected in C字符串比 C 中的预期长
【发布时间】:2015-11-14 10:36:45
【问题描述】:

这是我的代码

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

int main(){
    char pal[8] = "ciaooaic";
    char pal1[7] = "ciaoaic";
    int lenPal = strlen(pal);
    int lenPal1 = strlen(pal1);
    printf("strlen('%s'): %d\n", pal, lenPal);
    printf("strlen('%s'): %d\n", pal1, lenPal1);
    return 0;
}

问题是当我运行这段代码时,输​​出是:

strlen('ciaooaicP@'): 11
strlen('ciaoaic'): 7

第一个字符串在 P 和 @ 之间还有另一个不可打印的字符。我是菜鸟,所以也许我错过了一些明显的东西。有人可以帮我吗?

编辑:

只需多留一个空格,例如 char pal[9] = "ciaooaic"; char pal1[8] = "ciaoaic";

它有效,但为什么呢?我知道 \0 应该有一个空格,但是“ciaoaic”没有它也可以工作......

【问题讨论】:

  • 只需多留一个空格,例如char pal[9] = "ciaooaic"; char pal1[8] = "ciaoaic";
  • 由于未定义的行为,您的代码可能会给出任何输出(甚至是正确的输出)。
  • 当你初始化字符串时,例如char pal[] = "ciaooaic"; 编译器将在末尾包含空终止符(注意:'\0'0 是等效的)。当您指定尺寸时,例如pal[8],您将数组的大小限制为该大小。如果您碰巧用字符填充它们并且没有为空值留出空间,编译器会很高兴,因为它相信您知道您的意思。如果碰巧,内存中char pal[8] = "ciaooaic"; 之后的下一个字符是0,那么您会意外地得到一个以空字符结尾的字符串。不要指望这种情况经常发生......
  • palpal1 都不是 C11 §7.1.1 ¶1 定义的字符串:字符串是由第一个空字符终止并包括第一个空字符的连续字符序列。术语多字节字符串有时用于强调对字符串中包含的多字节字符进行特殊处理或避免与宽字符串混淆。指向字符串的指针是指向其初始(最低地址)字符的指针。字符串的长度是空字符之前的字节数,字符串的值是所包含字符的值的顺序,按顺序排列。
  • 关于允许非字符串初始化的措辞参见 C11 §6.7.9 Initialization ¶14字符类型的数组可以由字符串文字或 UTF-8 字符串文字进行初始化,可选地包含在大括号。字符串文字的连续字节(如果有空间或数组大小未知,则包括终止的空字符)初始化数组的元素。 ¶2 是一个约束:没有初始化器尝试为未包含在正在初始化的实体中的对象提供值。

标签: c string strlen


【解决方案1】:

1.当您将它们传递给strlen() 时,您不会为空终止符留出空间,因此您的代码会表现出未定义的行为 -

char pal[8] = "ciaooaic";
char pal1[7] = "ciaoaic";

'\0' 留一个空间。像这样声明和初始化 -

char pal[9] = "ciaooaic";
char pal1[8] = "ciaoaic";

2.strlen()返回size_t而不是int,所以这样写-

size_t lenPal = strlen(pal);
size_t lenPal1 = strlen(pal1);

并使用%zu 说明符来打印这两个变量。

【讨论】:

  • size_t 就是unsigned int,为什么不一样?
  • @Dmaster:因为unsigned int 不是int。而size_t 也可以是unsigned long
  • @DMaster 那是实现定义它将是什么类型,还有其他无符号类型。
  • 即使size_t 不是unsigned int,但这不会导致问题,我们甚至可以将其转换为short,它仍然显示相同。为什么要在答案中提及?
  • @DMaster 点是 strlen 返回 size_t 而不是 intunsigned int 。这就是我提到的原因,我认为这没有任何害处。而且,如果你愿意,它应该是unsigned int,而不是int
【解决方案2】:

您没有为 NULL 终止字符 \0 保留空间。


要么将数组大小增加1

char pal[9] = "ciaooaic";
char pal1[8] = "ciaoaic";

根本不指定长度

char pal[] = "ciaooaic";
char pal1[] = "ciaoaic";

【讨论】:

    【解决方案3】:

    以上两个答案都足以解决你的疑惑。 将 pal 和 pal1 的长度都加一,因为最后没有空间用于分配空字符('\0')。 但是,使用 printf 打印非空终止字符有一个小技巧

    printf("strlen('%.*s'): %d\n",8, pal, lenPal);
    printf("strlen('%.*s'): %d\n",7, pal1, lenPal1);
    

    上述技巧的链接:BRILLIANT

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-11
      • 2015-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      相关资源
      最近更新 更多