C++中的” – >”运算符是什么?

看完后隐藏功能和C++/STL的暗角上comp.lang.c++.moderated,我完全惊讶的是,下面的代码片断编译并在两个Visual Studio 2008和G ++ 4.4的工作.

这是代码:

#include <stdio.h>
int main()
{
    int x = 10;
    while (x --> 0) // x goes to 0
    {
        printf("%d ", x);
    }
}

我假设这是C,因为它也适用于GCC.标准中定义了哪里,它来自何处?

回答

-->不是运营商.它实际上是两个独立的运营商,--而且>.

条件的代码递减x,同时返回x原始(未递减)值,然后0使用>运算符比较原始值.

为了更好地理解,该声明可以写成如下:

while( (x--) > 0 )
  • 然后,它在某种情况下看起来像某种范围运算符.
  • 假设x后递减然后与0比较,则说x在与0比较后递减
  • 在Java中它也编译:)
  • 它的名字@Jay是糟糕的编程风格:-)这就是问题首先被问到的事实.将操作符文本绑定到它们正在操作的东西而不是不相关的东西更有意义,因此`while(x--> 0)`会更合适.它还使得正在发生的事情变得更加明显(至少在固定字体编辑器中)意味着这个答案中的括号不是必需的.
  • 我不认为它是一样的.我认为"then"这个词意味着有一个顺序(在减少后,x的值减少一个).我想有人可以说"你递减递减x然后比较它的旧值和0 ......"以使其更清晰.但无论如何这都是挑剔.我们都知道这是什么意思.
  • I've seen it jokingly referred to as the "downto" operator (https://codegolf.stackexchange.com/questions/16226/i-need-a-program-where-the-user-inputs-an-array-of-doubles-and-the-program-outpu/16232#16232)
  • 恕我直言"为了更好地理解,声明可以如下:"`while(x> 0){x--; printf("%d",x); 或者甚至更好:一个for循环.
  • 符号 - >经常被更多的数学纯粹程序员使用,我甚至听说它被称为"倾向于",因为它实际上是在许多情况下用于它的行为.关于` - )`这是垂直的双截面笑脸......; D或'预定香蕉`,无论你喜欢什么:D
  • 请注意,我并不是说你必须在操作符和操作数之间留出空格(比如`a + b`)只是因为它们不应该给出不平衡的偏好(`a + b`或`a + b`)或不正确的偏好(在问题中,或者`char*x,y`(这是一个char指针和一个char,因此最好写成`char*x,y`或`char y,*x)以避免可能的混淆).

或者对于完全不同的东西...... x幻灯片到0

while (x --\
\
\
\
> 0)
printf("%d ", x);

不是那么数学,但......每张图片都描绘了千言万语......

  • @mafutrct - 我记得它在C中只是追加下一行,好像没有换行符.这里的\ s基本上什么都不做.
  • 是的,这个模糊不清的幻灯片操作员.我怎么会忘记!
  • 对不起,我没有得到这个.这是如何运作的?
  • IIRC,K&R C允许在减量运算符中的' - '之间的空格,在这种情况下,你可以在它的中间有反斜杠,这看起来更酷.:)
  • @ArnavBorborah这是一个古老的表达方式,意思是"为什么在图片做得更好时浪费文字",在这种情况下用作笑话.(事实上​​有2个关键字`while`和`printf`)
  • @mafu'\'字符告诉编译器当前行在下一行继续,因此编译器应合并两行并编译为一行.'while(x - > 0)'将一直运行,直到x等于-1.但是,他制作缩进的方式使得x看起来像是滑向零.'当x滑到0 ......'

这是一个非常复杂的操作员,所以即使ISO/IEC JTC1(联合技术委员会1)也将其描述放在C++标准的两个不同部分.

开玩笑一边,它们是两个不同的运营商:-->分别在§5.2.6/ 2和C++ 03标准的§5.9中描述.


它相当于

while (x-- > 0)

x--(post decrement)相当于x = x-1,代码转换为:

while(x > 0) {
x = x-1;
// logic
}
  • 这不太对.在第二种情况下,循环体内的x值是不同的.您的示例中的赋值语句应该是*高于它的逻辑,以使其等效.后缀 - 减去1,但比较将发生在*减去前*的值.
  • 它们仍然不相等。在第一个循环之后,x为-1(或在无符号的情况下溢出),在第二个循环之后为0。(假设x开始为非负数,则两个循环都不会修改x或中断或...)
  • @uliwitness这些是真正等效的。如果使用前缀,那将是错误的:`0&gt;-x`在这种情况下,`x`在逻辑之前递减。在后缀中,逻辑在减量之前执行,因此两个样本都是等效的。随时将它们编写在“控制台”中并进行测试。

x 在相反的方向上可以更快地变为零:

int x = 10;
while( 0 <---- x )
{
printf("%d ", x);
}

8 6 4 2

你可以用箭头控制速度!

int x = 100;
while( 0 <-------------------- x )
{
printf("%d ", x);
}

90 80 70 60 50 40 30 20 10

😉

  • 用"激光器"归零.while(0> - - - - - - - - - - ---------- x)...相同的输出.
  • 虽然它应该是显而易见的,对于每个刚接触C++的人来说:不要这样做.如果您需要增加/减少多个,请使用增强赋值.
  • "You can control speed with an arrow!". Thanks, I hate it.
  • @doc它用c ++编译,但不用c编译.
  • An apt answer to the question.
  • 哪个操作系统,这种类型的输出生成,我使用的是ubuntu 12.04,因为我有一个错误信息
  • @phord你确定它不编译? - > http://coliru.stacked-crooked.com/a/5aa89a65e3a86c98
  • 我刚刚检查过,两个`对面的'运算符和激光`BIU ~~`运算符都不是那么快,因为它们不能被gcc优化!
  • 是的,[这不能在C中编译](http://stackoverflow.com/q/42355908/7292857).

它的

#include <stdio.h>
int main(void){
int x = 10;
while( x-- > 0 ){ // x goes to 0
printf("%d ", x);
}
return 0;
}

只是空间使事物看起来很有趣,--减少和>比较.


用法-->具有历史意义.减少(在某些情况下仍然是),比在x86架构上递增更快.使用-->表明,x将要0,并呼吁那些有数学背景.

  • 不完全正确.递减和递增需要相同的时间,这样做的好处是,与比较变量相比,与零的比较非常快.许多架构都是如此,而不仅仅是x86.任何带有JZ指令的东西(如果为零则跳转).你可以找到许多向后写的"for"循环来节省比较周期.这在x86上特别快,因为递减变量的行为适当地设置了零标志,因此您可以在不必明确比较变量的情况下进行分支.
  • 好吧,递减到零意味着你只需要与每个循环迭代的0进行比较,而向n迭代意味着与每次迭代的n进行比较.前者往往更容易(在某些架构上,在每次数据寄存器操作后都会自动测试).
  • 增量和减量同样快,可能在所有平台上(绝对在x86上).不同之处在于测试循环结束条件.要查看计数器是否已达到零实际上是空闲的 - 当您递减一个值时,在处理器中设置零标志并检测您只需要检查该标志的结束条件,而在结束条件之前需要增加比较操作时可以检测到.
  • @burrito虽然我并不反对,但通常会非常接近地预测以非零值为条件的循环.
  • 当然,由于现代编译器可以自动进行矢量化和反向循环,所以现在所有这些都没有实际意义.
  • 在x86 ASM中,`LOOP <地址>`减少`ECX`寄存器,然后跳转到`<address>`,除非'ECX`的递减导致零.将循环计数器递减为零允许编译器生成单个"LOOP"指令,而递增或计数到其他值需要单独的INC/DEC/ADD/SUB,比较和条件跳转指令.如果在循环中没有使用`counter`的值,现代编译器通常可以将其他循环转换为`counter - > 0`循环.
  • @Konerak从O(N)操作到O(1)操作几乎总是优选的.
  • 继续我之前的评论:`MOV ECX,value`,`@start:`,`<code>`,`LOOP @ start`是`counter = value - 1的x86 ASM等价物; while(counter - > 0){<code>; }`.请注意,如果`value`最初为零,它会barf,因此在循环前需要额外检查.

while( x-- > 0 )

是如何解析的.


非常极客,但我将使用这个:

#define as ;while
int main(int argc, char* argv[])
{
int n = atoi(argv[1]);
do printf("n is %d\n", n) as ( n --> 0);
return 0;
}
  • @EJP它确实编译.语法是`do statement while(expression);`.话虽如此,我希望我理解这个例子就是一个笑话.
  • @SAFX - 用[埃及括号](http://www.codinghorror.com/blog/2012/07/new-programming-jargon.html)完全是象形文字
  • I know it looks way cool, but I fear it's deceptive. The reason you're writing C++ instead of Machine Language is b/c you want to convey your intent to the next guy reading your code. This construct violates the principle of least surprise. It is a mental "trip hazard."
  • “当 n 趋近于零时”有点酷,以一种极客的微积分方式:-)

我读过的一本书(我不记得哪本书正确)说明:编译器尝试使用左右规则将表达式解析为最大的标记.

在这种情况下,表达式:

x-->0

解析最大的代币:

token 1: x
token 2: --
token 3: >
token 4: 0
conclude: x-- > 0

同样的规则适用于此表达式:

a-----b

解析后:

token 1: a
token 2: --
token 3: --
token 4: -
token 5: b
conclude: (a--)-- - b

我希望这有助于理解复杂的表达式^^

  • 你的第二个解释是不正确的.编译器将看到`a ----- b`并认为`(a - ) - - b`,它不能编译,因为`a - `不返回左值.
  • @DoctorT:它通过词法分析器.只有语义传递能够发出错误.所以他的解释是正确的.
  • 另外,`x`和`--`是两个独立的标记.
  • 这被称为[Maximal munch](https://en.wikipedia.org/wiki/Maximal_munch).
  • 只要你认为` - >`是一个操作符(这就是提出问题就暗示了这一点),这个答案根本就没有用 - 你会认为令牌2是` - >`,而不是只是` - `.如果你知道` - >`不是运算符,你可能在理解问题中的代码时没有问题,所以,除非你有一个完全不同的问题,否则我不确定这是怎么回事有用.
  • @DoctorT示例可以是正确的,假设`a`有超载的后递减运算符,它返回左值.http://coliru.stacked-crooked.com/a/e1effc351ae79e9f
  • 它解释了为什么它不被解析为'a - - > b`,因为` - >`是一个运算符本身.

这完全一样

while (x--)
{
printf("%d ", x);
}

对于非负数

  • 这不应该是`for( - x ++; - x; ++ x - )`?
  • @MateenUlhaq,根据标准,这是错误的表达式` - x ++`根据§1.9.15具有未定义的行为
  • @DoctorT这就是`unsigned`的用途
  • `while (x --> 0)` is **not** the same as `while (x--)` if `x` has a signed type, the first loop does not execute at all if `x` has a negative value but the second iterates many times until it hits undefined behavior when `x` reaches `INT_MIN`.

无论如何,我们现在有一个"去"操作员."-->"很容易被人们记住作为一个方向,而"当x变为零"意味着直接.

此外,它比"for (x = 10; x > 0; x --)"某些平台更有效.

  • @Josh:实际上,溢出为`int`提供了未定义的行为,所以它可以很容易地吃你的狗,如果它开始为负,则把'x`变为零.
  • 当x的值为负时,尤其是不可能.
  • 另一个版本没有做同样的事情 - 使用`for(size_t x = 10; x - > 0;)`循环体用9,8,..,0执行,而另一个版本有10, 9,...,1.使用无符号变量将循环降低到零是非常棘手的.
  • 我认为这有点误导......我们没有字面上的"去"操作符,因为我们需要另一个`++>`来做增量工作.
  • 由于@PeteKirkham在comnmet中给出的原因,这对我来说是一个非常重要的习惯用法,因为我经常需要将无符号量的循环减少到"0".(为了比较,省略测试为零的成语,例如写'while(n - )`代替unsigned`n`,没有给你买任何东西,对我来说极大地妨碍了可读性.)它也有你指定的令人愉快的属性_in more_比初始索引,这通常是你想要的(例如,对于指定其大小的数组循环).我也喜欢` - >`没有空格,因为这使得这个成语容易识别.

此代码首先比较x和0,然后递减x.(也在第一个答案中说:你是后递减x,然后将x和0与>运算符进行比较.)请参阅此代码的输出:

9 8 7 6 5 4 3 2 1 0

我们现在首先通过在输出中看到0进行比较然后递减.

如果我们想先减少然后比较,请使用以下代码:

#include <stdio.h>
int main(void)
{
int x = 10;
while( --x> 0 ) // x goes to 0
{
printf("%d ", x);
}
return 0;
}

那个输出是:

9 8 7 6 5 4 3 2 1
  • `--x> 0` Is that x in a spaceship going towards **0** (the moon)?

运行此代码时,我的编译器将打印出9876543210.

#include <iostream>
int main()
{
int x = 10;
while( x --> 0 ) // x goes to 0
{
std::cout << x;
}
}

正如所料.在while( x-- > 0 )实际意义while( x > 0).该x--职位递减x.

while( x > 0 )
{
x--;
std::cout << x;
}

是一种不同的写作方式.

很好,原来看起来像"虽然x变为0".

  • `while(x--> 0)实际上意味着while(x> 0)` - 我不确定你在那里试图说什么,但你用它的方式暗示` - `没有任何意义,显然是非常错误的.
  • 当您在同一语句中多次递增/递减同一个变量时,结果只是未定义的.它不适用于这种情况.

--和之间缺少空间>.x后递减,即在检查条件后递减x>0 ?.

  • 空间不会丢失 - C(++)忽略空格.
  • @Jens怎么样:"空间没有丢失 - C(++)忽略了不必要的空白区域."?
  • @ H2CO3这一般不是这样.有些地方必须使用空格来分隔标记,例如`#define foo()`与`#define foo()`.

--递减运算符,>大于运算符.

两个运算符作为单个运算符应用-->.

  • 它们被_applied_作为它们的两个独立运算符.他们只是误读了"看起来像一个人".

它是两个运营商的组合.第--一个用于递减值,>用于检查该值是否大于右侧操作数.

#include<stdio.h>
int main()
{
int x = 10;
while (x-- > 0)
printf("%d ",x);
return 0;
}

输出将是:

9 8 7 6 5 4 3 2 1 0

实际上,x是后递减,并且正在检查该条件.它不是-->,它是(x--) > 0

注意:x在检查条件后更改值,因为它会后递减.也可能发生一些类似的情况,例如:

-->    x-->0
++>    x++>0
-->=   x-->=0
++>=   x++>=0
  • 除了++>几乎不能在while()中使用.一个"向上......"运算符将是++ <,它看起来并不好看.操作员 - >是一个幸福的巧合.
  • @BenLeggiero这可以"生效"在生成代码的意义上(同时激怒那些不喜欢虚假代码的读者),但语义是不同的,因为它使用预定义意味着它将执行少一次迭代.作为一个人为的例子,如果`x`从1开始,它将永远不会执行循环体,但是`while((x--)> 0)`会.{edit} Eric Lippert在他的C#4发行说明中提到了这两点:https://blogs.msdn.microsoft.com/ericlippert/2010/04/01/some-last-minute-new-c-4-0-features/

C和C++遵守"最大蒙克"规则.a --- b被翻译成同样的方式(a--) - b,在你的情况下 x-->0翻译成(x--)>0.

规则本质上是从左到右,表达式是通过获取将形成有效表达式的最大字符来形成的.

  • OP假设的是:"((a) - >)"是最大的蒙克.事实证明OP的原始假设是不正确的:" - >"不是最大有效运算符.
  • 如果我没记错的话,也称为贪心解析.
  • @RoyTinker Greedy *scanning.* 解析器与此无关。

为什么所有的并发症?

原始问题的简单答案就是:

#include <stdio.h>
int main()
{
int x = 10;
while (x > 0)
{
printf("%d ", x);
x = x-1;
}
}

做同样的事情.不是说你应该这样做,但它做了同样的事情,并且会在一篇文章中回答这个问题.

x--只是上述的简写,>只是一个正常的大于operator.没什么大不了的!

现在有太多的人把简单的事情弄复杂了;)

  • 这里的程序给出了不同于原始的输出,因为这里的x在printf之后递减.这很好地证明了"简单答案"通常是不正确的.
  • 这个问题不是关于并发症,而是关于**隐藏的功能和C++/STL的黑暗角落**
  • `OP的方式:9 8 7 6 5 4 3 2 1 0`和`The Garry_G方式:10 9 8 7 6 5 4 3 2 1`
  • 它不会做同样的事情。将您的x = x-1移到printf之前,然后您可以说“它做同样的事情”。

传统的方式我们定义的条件,而循环括号" while'和终止条件的括号内’ ()",但这{}-->一个办法一个定义的一次.例如:

int abc(void)
{
int a = 5
while((a--) > 0) // Decrement and comparison both at once
{
// Code
}
}

它说,减少a并运行循环直到时间a大于0

其他方式应该是这样的:

int abc(void)
{
int a = 5;
while(a > 0)
{
a--;
// Code
}
a--;
}

两种方式,我们做同样的事情,实现相同的目标.

  • 这是不正确的.问题中的代码是:'test-write-execute'(先测试,编写新值,执行循环),例如'test-execute-write'.

(x --> 0)是指(x-- > 0)

  1. 您可以使用 (x -->)
    Output: 9 8 7 6 5 4 3 2 1 0
  1. 你可以用(-- x > 0) 它的意思(--x > 0)
    Output: 9 8 7 6 5 4 3 2 1
  1. 您可以使用
(--\
\
x > 0)

Output: 9 8 7 6 5 4 3 2 1

  1. 您可以使用
(\
\
x --> 0)

Output: 9 8 7 6 5 4 3 2 1 0

  1. 您可以使用
(\
\
x --> 0
\
\
)

Output: 9 8 7 6 5 4 3 2 1 0

  1. 你也可以使用
(
x
-->
)

Output: 9 8 7 6 5 4 3 2 1 0

同样,您可以尝试多种方法来成功执行此命令。


char sep = '\n'  /1\
; int i = 68    /1  \
; while (i  ---      1\
\
/1/1/1                               /1\
/1\
/1\
/1\
/1\
/           1\
/            1 \
/             1  \
/              1   \
/1            /1    \
/1          /1      \
/1        /1        /1/1> 0) std::cout \
<<i<<                               sep;

对于更大的数字,C++20 引入了一些更高级的循环功能。首先,i我们可以构建一个反向循环去循环并将其偏转到std::ostream. 但是,速度i是实现定义的,因此我们可以使用新的 C++20 速度运算符<<i<<来加快速度。我们还必须通过构建 wall 来捕捉它,如果我们不这样做,i就会离开作用域并取消引用它会导致未定义的行为。要指定分隔符,我们可以使用:

 std::cout \
sep

我们有一个从 67 到 1 的 for 循环。

  • I came here looking for bronze, instead I found gold...

您可以使用穿甲箭头运算符来代替常规箭头运算符 (-->):--x>(注意箭头尖端上的那些尖锐倒钩)。它为穿甲加 1,因此它比常规箭头运算符更快地完成循环 1 迭代。自己试试:

int x = 10;
while( --x> 0 )
printf("%d ", x);

以上是C++中的” – >”运算符是什么?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>