【问题标题】:pointers and increment operator指针和增量运算符
【发布时间】:2015-10-21 13:22:41
【问题描述】:

我有以下简单的代码:

#include<iostream>

const char str[]={'C','+','+'};

int main()
{ 
  const char *cp=str;                     
  std::cout<<*str<<std::endl;

  while (*cp++>0)  
    std::cout<<*cp;
} 

不明白为什么会打印出来

C
++

后缀增量运算符不应该评估表达式但返回值不变吗? (我仔细检查了增量、取消引用和关系运算符的优先级,它应该可以工作)

【问题讨论】:

  • 你期望什么输出?
  • 我认为我在 cp 增加之前取消了它的引用。所以我期待它打印整个字符串。
  • 您正在将'\0' 打印到cout 流。这是 this question 中某些人指出的 UB。
  • “所以我希望它打印整个字符串”。它正在打印整个字符串,它只是插入一个额外的换行符(和一个\0
  • 否,因为第一次调用 cout 独立于第二次调用。也许我的代码不够清晰。但我发现了我的错误,所以还是谢谢你。

标签: c++ pointers post-increment c-strings


【解决方案1】:

你的问题在这里:

while (*cp++>0)  
    std::cout<<*cp;

后缀运算符在计算它所使用的表达式之后增加值。在这个while 语句中有两个不同的表达式引用cp:第一个测试和递增,但第二个打印。由于第二个是单独的语句,此时增量已经发生。

即您当前针对'C' 进行测试,然后不管结果如何都递增,然后通过现在递增的指针打印'+'。如果它正在迭代字符串文字,则此代码在到达 0 后也会增加一次,尽管您看不到结果,因为它跳过了打印(因为它迭代了一个没有空终止符的手动创建的数组, 它实际上在这里所做的是从结尾处掉下来并表现出未定义的行为;这本身就是一个很大的错误,如果没有放在那里,你不能依赖最后有一个零。

【讨论】:

  • 哇,是的,我明白了,第一个增量发生,无论在什么情况下...非常感谢!
【解决方案2】:

这一行打印:C 和回车。

std::cout<<*str<<std::endl;

然后你在后面的字符上循环,但没有结束字符(c.f.缓冲区溢出)
这是修复的代码。

#include <iostream>

const char str[]={'C','+','+', '\0'};

int main()
{ 
    const char* cp = str;                     
    std::cout<< *str << std::endl;

    while (*cp++ > 0)  
    std::cout << *cp;

    return 0;
}

如果要显示“C++”,这段代码就更简单了

#include <iostream>

const char str[]={'C','+','+', '\0'};

int main()
{ 
    const char* cp = str;                     

    while (*cp > 0)
        std::cout << *cp++;

    std::cout << std::endl;

    return 0;
}

【讨论】:

  • 更简单:std::cout &lt;&lt; str &lt;&lt; '\n'; ...
【解决方案3】:

在一行

while(*cp++>0)

后自增运算符在求值发生后执行。

即cp 在第一次评估 while 条件时指向 C

所以,

*cp => 'C' which is greater than 0.

在移动到下一行之前(循环内),执行后自增运算符,使 cp 指向第一个 +

打印+后,再次执行while条件,这次*cp返回'+'。从'+' &gt; 0 开始,控件第二次进入循环。

在进入循环之前,后自增运算符再次执行,使cp指向第二个'+',并打印出来。

现在,while 条件第三次执行。在这里,*cp 返回+。因此,控制再次进入循环。

在进入循环之前,后增量再次执行。这一次,它使 cp 指向下一个字符,即\0

\0 被打印出来,这对这段代码没有影响。然后,当while条件再次执行时,*cp返回\0,而不是>0。所以,条件失败。

编辑: 在 cmets 中看到您想在同一行中打印整个字符串。将循环更改为:

while(*cp > 0)
    std:cout<<*cp++;

【讨论】:

    【解决方案4】:

    后缀自增运算符不应该计算表达式但返回值不变吗?

    不,后缀运算符先返回操作数的值,然后增加1。

    这里,

    while (*cp++>0)  
        std::cout<<*cp;
    

    当它到达std::cout&lt;&lt;*cp; 时,cp 的值会增加,因此结果是++

    【讨论】:

    • 这正是 OP 所说的。
    • 返回值不变??真的吗?
    • @luca *cp++ > 0 它将首先评估表达式,*cp &gt; 0 然后它将增加指针 cp++
    • 嗯,是的:“首先返回值 [然后增加它]”和“返回值不变”确实是同义词。
    • "unchanged" 意味着它从未真正改变过,这是不正确的。我更喜欢“返回原始值”。这强调了cp 确实发生了变化。
    猜你喜欢
    • 2018-01-18
    • 2018-05-14
    • 2010-12-27
    • 2013-10-20
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    相关资源
    最近更新 更多