【问题标题】:Some questions about strings关于字符串的一些问题
【发布时间】:2020-07-25 22:46:20
【问题描述】:

我遇到了一个问题。在下面的代码中,我预计字符串 p 的长度是 3,但实际长度是 6。这是我想知道的第一个地方。然后,我自己调试的时候,调试出来的p的长度和预期的结果是一致的。这让我感到非常不解。不知道为什么p的长度是6,调试的时候为什么长度变成3。 .有人可以回答这个问题吗?

#include <cstring>
#include <cstdio>

int main()
{
    char p[]={'a','b','c'}, q[10] = {'a','b','c'};
    printf("%p  %p\n",&q,&p);
    printf("%d  %d\n",strlen(q),strlen(p));
    return 0;
}

pic-1 pic-2

【问题讨论】:

  • p 不是以空值结尾的; strlen 一直计数直到它看到一个空值(或者你的程序被中止,因为你访问了不属于你的内存)。
  • 您在p 上使用strlen,而p 不履行使用strlen 的约定,从而导致未定义的行为。对于未定义的行为,任何事情都可能发生。该程序可能会产生荒谬的结果。它可能看起来工作正常。它可能会崩溃。或任何其他无法解释的行为。
  • 注意q被初始化了,初始化器中没有提供的任何数组元素都设置为null。

标签: c++ c arrays string initialization


【解决方案1】:

问题是,p 不是以 null 结尾的字符数组,所以不能用作 字符串。将其用作期望 string 的函数调用的参数,将导致 undefined behaviour (UB).

包含 UB 的程序的输出不能以任何方式证明。

为了添加更多上下文,q 以空值结尾,根据参数小于聚合大小的初始化器列表的规则,其余成员将被初始化,就好像它们具有静态存储一样,所以在 @ 987654324@ 类型,它们被初始化为0(这是字符串所需的空终止符)。因此,使用q 作为字符串就可以了。

解决方案:

你可以

  • 提及比初始化列表的元素更多的维度
  • 将一个空值作为初始化器列表中的最后一个元素{'a','b','c', '\0'}
  • 使用字符串(而不是初始化列表)来初始化数组,例如"abc",它将在数组中包含空终止符。

【讨论】:

  • 谢谢。其实这道题是考试题,我的选择是3和3。看来题可能不严谨
  • 好的,我再次确认了这个问题。正确答案提到p的长度未知,q的长度为3。
  • @tangger 是的,给你。
  • @tangger - 实际上这个问题很严格。 strlen(p) 的计算给出了未定义的行为。此外,strlen() 返回一个 size_t - 这是一个无符号类型 - 因此使用 %d 打印它(预计将提供一个 int,并且如果未传递 int 则具有未定义的行为)也给出未定义的行为。所以 3 和 3 不是保证输出。事实上,如果你给出的答案是任何特定的输出都是预期的,那么你的答案是不正确的。在调试和发布版本之间获得不同的行为是未定义行为的典型(不保证)症状
【解决方案2】:

p 不是以空值结尾的; strlen 一直计数直到它看到一个空值(或者你的程序被中止,因为你访问了不属于你的内存)。

注意q初始化,初始化器中未提供的任何数组元素都设置为null。

【讨论】:

    【解决方案3】:

    在 C 中,字符串必须以空字节结尾,这就是 strlen 找到它们的长度的方式。像这样声明你的字符串,长度会正确显示:

    char p[]={'a','b','c', '\0'}, q[10] = {'a','b','c', '\0'};
    

    【讨论】:

    • char p[]="abc", q[10] = "abc";
    • 请注意,q 已经正确 - 对于数组,{} 初始化提供的元素数量,其余元素初始化为零。 char q[10] = {'a','b','c'}; 保证有 abc 和 7 个零。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    相关资源
    最近更新 更多