【问题标题】:Increment operator not working in while condition增量运算符不在while条件下工作
【发布时间】:2021-07-14 11:04:11
【问题描述】:

我写了一个while循环来增加一个指针,直到内容为空字节或相邻元素之间的差异大于1,这工作正常:

while (i[1] && *i + 1 == i[1]) i++;

然后我尝试将其重写为:

while (i[1] && *(i++) + 1 == *i);

但这样一来,它就陷入了无限循环,好像i 没有被递增。为什么会这样?

编辑: 我必须为误导而道歉,但我现在发现它并没有卡在我向您展示的 while 循环中,而是简单地退出了该 while 循环,而是卡在了它的父循环中,让我与您分享整个代码:

      char accepted[strlen(literal)+1];
      strcpy(accepted, literal);
      std::sort(accepted, accepted + strlen(accepted));
      char *i = accepted-1;
      while (*++i){
        uint8_t rmin = *i; 
        //while (i[1] && *i + 1 == i[1]) i++;
        while (i[1] && *(i++) + 1 == *i);
        uint8_t rmax = *i; 
        ranges.push_back(Range{rmin, rmax});
        if (!i[1]) break;//is this necessary?
      }  

我的问题不再有效。

是的,“聪明”的不可读代码是个坏主意。

【问题讨论】:

  • 因为未定义的行为。聪明通常不是。
  • @molbdnilo 我在这里看不到 UB(至少乍一看),而是i 没有增加,因为如果i[1] 不为零,那么*(i++) 永远不会被评估,因此无限循环。但确实,“聪明”的不可读代码通常是个坏主意
  • 第二个表达式具有未定义的行为,因为编译器可以以任何顺序评估这些术语。在第一个表达式中,情况并非如此。
  • @molbdnilo 不,你是对的,看我之前的评论,但是有两个问题,你提到的UB和我在第一条评论中提到的短路评估问题
  • Brian Kernighan:“调试的难度是一开始编写代码的两倍。因此,如果你尽可能巧妙地编写代码,那么根据定义,你就不够聪明,无法调试它。”

标签: c++ pointers operators post-increment


【解决方案1】:

你的代码有两个问题:

while (i[1] && *(i++) + 1 == *i);
  • && 运算符使用short circuit evaluation,即如果左侧部分 (i[1]) 为 0,则永远不会计算右侧部分 (*(i++) + 1 == *i)。这就是您的代码无限循环的原因。
  • 表达式 *(i++) + 1 == *i 产生未定义的行为,因为未指定 == 左右子表达式的 order of evaluation。

通常不建议编写“聪明”的代码。编写可读的代码,让编译器负责优化。

【讨论】:

  • 感谢您的回答,但是在评估&&时,难道不是反过来,即只有当左侧部分i[1]为0时,才不会评估右侧部分?我的理由是,要评估 AND 门,您只需要检查其中一个是否为假。
  • @Cabbache 你是对的,我更正了答案。
  • 太好了,感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2019-07-07
  • 1970-01-01
  • 2013-09-23
  • 2013-07-30
  • 2017-10-02
  • 1970-01-01
  • 2023-01-14
相关资源
最近更新 更多