【问题标题】:strlen returning wrong value for 2d arraystrlen 为二维数组返回错误值
【发布时间】:2023-03-22 19:20:02
【问题描述】:

为什么会这样:

char animals[][30] = {{"cow "}, {"dog "}, {"frog "}, {"gecko "}, {"cat"}};

当我这样做时返回 4 而不是 5:

printf("%d\n", strlen(animals));

据我所知,字符数组有 5 个不同的数组,所以我不确定为什么说有 4 个。

【问题讨论】:

  • animals 不是字符串
  • 您应该收到关于animalsstrlen() 的参数之间类型不匹配的警告
  • strlen 是“字符串长度”的缩写。为什么你会期望它返回数组中的元素数量?

标签: c multidimensional-array c-strings strlen


【解决方案1】:

此声明

char animals[][30] = {{"cow "}, {"dog "}, {"frog "}, {"gecko "}, {"cat"}};

不声明包含字符串的一维数组。

函数strlen的参数类型应为char *。但是您使用的是char ( * )[30] 类型的参数。

您需要的是以下内容

printf( "%zu\n", sizeof( animals ) / sizeof( *animals ) );

我不知道为什么它说有 4 个。

因为在此调用 printf 时使用了无效的转换说明符 %d 而不是 %zu

printf("%d\n", strlen(animals));

调用中参数animals的值

strlen(animals)

被认为是数组的第一个元素的地址,其长度确实等于4

这是从这个调用的地址相等的角度来看

strlen(animals)

相当于调用

strlen(animals[0])

因为第一次调用中使用的animals 的值等于它的第一个元素地址animals[0] 的值。尽管在第一次调用 strlen 时,参数的类型无效。

编译器应该发出一条消息,表明您在调用 strlen 时使用了不正确的参数。

【讨论】:

  • 其实相当于strlen(&animals[0])
  • @Barmar 与动物[0]相同。所有这些表达式都有相同的值。
  • @Barmar 所有架构都需要它。数组的地址等于它的第一个元素的地址。
  • @VladfromMoscow 但这似乎与6.2.5 Types, p28 相矛盾:“...指向其他类型的指针不需要具有相同的表示或对齐要求。”对this question 的公认答案甚至声明没有明确要求数组的地址等于其第一个元素的地址。似乎是一个很好的语言律师问题。
  • @AndrewHenle 数组的元素类型不是“另一种类型”多维数组的地址是它的第一个元素的地址和第一个元素的第一个元素的地址。所有三个值都是相等的,并且是分配给数组的范围的地址..
【解决方案2】:

strlen() 用于计算字符串的长度(C 中以空字符结尾的字符序列),而不是用于计算数组元素的数量。

要获得数组的元素个数,可以用数组的大小除以数组元素的大小。

printf("%zu\n", sizeof(animals) / sizeof(*animals));

还请注意,您应该使用%zu,而不是%d,来打印size_tstrlen()sizeof 返回size_t

【讨论】:

    【解决方案3】:

    调用printf("%d\n", strlen(animals));有多个问题

    • printf 格式应为 %zu,如果通过在调用点包含 <string.h> 已正确声明 strlen。这不太可能造成问题,但应该解决。
    • strlen() 采用 C 字符串,animal 不是 C 字符串,它是 char 的二维数组。你应该改为传递strlen(animal[0])。同样,这个错误不太可能造成问题,因为二维数组中第一个字符串的地址与数组本身的地址相同。要计算二维数组中的元素数量,请使用sizeof(animal) / sizeof(*animal)
    • 调用应该打印4(字符串"cow "有一个尾随空格)和一个换行符,返回值将是2作为printf输出的字符数。

    试试这个修改后的版本:

    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char animals[][30] = {{"cow "}, {"dog "}, {"frog "}, {"gecko "}, {"cat"}};
    
        printf("number of strings: %zu\n", sizeof(animals) / sizeof(*animals));
        for (size_t i = 0; i < sizeof(animals) / sizeof(*animals); i++) {
            printf("%zu: \"%s\", %zu chars\n", i, animals[i], strlen(animals[i]));
        }
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      您问题的基本答案

      “当我这样做时返回 4 而不是 5”

      当你这样做时

      printf("%d\n", strlen(animals));
      

      animals 是指向第一个字符串的指针,animals 以“cow \0........dog \0...”的形式存储在内存中,其中.....是直到下一个字符串的字节数组条目(如果未初始化,通常是随机内存)。当您 printf strlen of animals 时,它会返回 strlen of "cow"。

      您正在混合类型。c 允许这样做,因为它们实际上是指针,这就是编译器工作但它是错误的原因。

      要获得 5 作为结果,您需要这样做

      printf("%zu",sizeof(animals) /sizeof(animals[0]));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-24
        • 2016-04-14
        相关资源
        最近更新 更多