【问题标题】:Why does strlen() return strange result when array doesn't contain null terminator?为什么当数组不包含空终止符时 strlen() 会返回奇怪的结果?
【发布时间】:2015-11-26 12:21:42
【问题描述】:

我有两个程序。两者都从字符串文字初始化数组。在一种情况下,数组大小正是我想要放入数组中的字符数。

我想知道为什么strlen() 返回的大小输出对于两个程序都不同。是因为缺少终止空字符吗?如果是,那为什么输出是 16?

#include<stdio.h>
#include<string.h>
main()
{
    char str[5] = "ankit";
    printf("size of = %d \n ",sizeof(str));
    int len = strlen(str);
    printf("length = %d \n ",len);
}

输出:- size of = 5 , length = 16

#include<stdio.h>
#include<string.h>
main()
{
    char str[] = "ankit";
    printf("size of = %d \n ",sizeof(str));
    int len = strlen(str);
    printf("length = %d \n ",len);
}

输出:- size of = 6,length = 5

【问题讨论】:

  • 你需要学习 C 字符串和空终止。
  • 如果一直走直线,为什么最后会掉进水里?
  • 如果数组不包含空终止符,则它不是字符串。 strlen() 与字符串一起使用,因此将这样的数组发送到 strlen() 是未定义的行为。
  • 空终止符告诉 C 当前字符串在哪里结束。如果没有,您的字符串将继续运行,直到您在内存中的其他地方遇到空终止符或您的程序崩溃。

标签: c arrays string


【解决方案1】:

在您的第一个代码中,通过编写

 char str[5] = "ankit";

您没有任何空间可供存储空终止符,这是 str 用作 string 所必需的。因此,在这种情况下,strlen() 通过溢出分配的内存来调用undefined behavior 以搜索空终止符。

OTOH,在第二个 sn-p,

char str[] = "ankit";

您将大小分配留给编译器,它会为用作初始值设定项的字符串文字中的元素加上空终止符分配内存。所以,你得到了想要的结果。

IMO,总是使用后一种方式,时不时省去很多头疼的事情。

【讨论】:

    【解决方案2】:

    您的char[5] 太短,无法容纳"ankit" 的值。

    正如您自己所说,C 样式字符串的末尾有 \0-termination。这意味着,您的字符串文字实际上在内部表示为 "ankit\0" (其中 \0 是单个字符)。

    由于strlen()-函数找不到\0 字符,它的行为是未定义的。

    这意味着,您需要一个 char[6] 来表示您的字符串。
    通过省略数组的显式长度,您可以让编译器选择大小(通过初始化,这在编译时是已知的)。因此,编译器会分配正确的大小(6 个字符)。

    【讨论】:

      【解决方案3】:

      是的,这是因为第一个示例中的数组没有为 0 终止符留出足够的空间。 strlen 的基本工作原理如下:

      size_t strlen( const char *str )
      {
        size_t len = 0;
        while( *str++ )
          len++;
        return len;
      }
      

      strlenstr 中第一个元素的地址 开始,然后“遍历”连续的地址,直到看到0 值字节。由于strlen 不知道对应于str 的数组实际上有多大(它得到的只是一个指向第一个元素的指针),它会一直越过数组的末尾,直到它看到0

      所有字符串都是char的数组,但不是char的所有数组都是字符串;如果没有零终止符,则不是字符串。

      【讨论】:

        【解决方案4】:

        char str[5] 最多可以占用 4 个字符,最后一个额外字节应保留为 '\0' 字符。因此其未定义的行为。

        【讨论】:

        • NULLnull 是两个不同的东西,不是吗?
        猜你喜欢
        • 2020-02-28
        • 2013-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多