Что такое оператор «->» в C ++?

8054

После прочтения Hidden Features и Dark Corners of С++/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. Где это определено в стандарте и откуда оно взялось?

  • 446
    Или даже просто правильный интервал ... Я не думаю, что когда-либо видел пробел между переменной и ++ или -- раньше ...
  • 13
    Я тоже был совершенно удивлен, когда увидел операторы «/ *» и « /» и подумал, что означает эта строка «i / 100 * / = N;» вычислить для?
Показать ещё 28 комментариев
Теги:
operators
code-formatting

25 ответов

7743
Лучший ответ

--> не является оператором. На самом деле это два отдельных оператора, -- и >.

Условный код уменьшает значение x, возвращая исходное (не уменьшенное) значение x, а затем сравнивает исходное значение с 0 с помощью оператора >.

Чтобы лучше понять, выражение может быть написано следующим образом:

while( (x--) > 0 )
  • 222
    С другой стороны, в этом контексте он действительно выглядит как некий оператор диапазона.
  • 95
    Сказать, что x пост-уменьшен и затем сравнивается с 0, то же самое, что сказать, что x уменьшается после сравнения с 0
Показать ещё 21 комментарий
2436

Или для чего-то совершенно другого... х скользит к 0

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

Не так математично, но... каждая картина рисует тысячу слов...

  • 42
    Извини, я этого не понимаю. Как это работает?
  • 180
    @mafutrct - насколько я помню \ в C просто добавляет следующую строку, как будто не было перевода строки. Здесь в основном ничего не делают.
Показать ещё 11 комментариев
2265

Это очень сложный оператор, поэтому даже ISO/IEC JTC1 (Joint Technical Committee 1) разместил свое описание в двух разных частях С++ Стандартный.

Шутя в сторону, это два разных оператора: -- и >, описанные соответственно в разделе 5.2.6/2 и в разделе 5.9 стандарта С++ 03.

1183

Это эквивалентно

while (x-- > 0)

x-- (после декремента) эквивалентно x = x-1 поэтому код преобразуется в:

while(x > 0) {
    x = x-1;
    // logic
}
  • 5
    Это не совсем верно. Значение x внутри тела цикла отличается во втором случае. Оператор присваивания в вашем примере должен быть выше логики, чтобы он был эквивалентным. Postfix - вычитает 1, но сравнение будет происходить со значением до вычитания.
  • 0
    @uliwitness Это действительно эквивалентно. Было бы неправильно, если бы использовался префикс: 0 >-- x В этом случае x уменьшается до логики. В постфиксе логика выполняется перед уменьшением, и, таким образом, оба образца эквивалентны. Не стесняйтесь записывать их в Console и тестировать их.
Показать ещё 1 комментарий
1009

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

;)

  • 3
    какая операционная система, этот тип вывода генерируется, я использую Ubuntu 12.04 в том, что у меня было сообщение об ошибке
  • 1
    Операционная система @Bhuvanesh не имеет значения. Это простой код C ++ (использующий printf() , потому что OP использует его), который должен компилироваться везде, поэтому это должна быть ваша ошибка. coliru.stacked-crooked.com/a/f5fdc710da0398c9
Показать ещё 7 комментариев
488

Это

#include <stdio.h>
int main(void){
     int x = 10;

     while( x-- > 0 ){ // x goes to 0

       printf("%d ", x);
     }

     return 0;
}

Просто пространство делает вещи забавными, -- уменьшается и > сравнивается.

361

Использование --> имеет историческую значимость. Decrementing был (и по-прежнему в некоторых случаях), быстрее, чем приращение архитектуры x86. Используя -->, предположим, что x подходит к 0 и обращается к тем, у кого есть математический фон.

  • 445
    Не совсем верно. Уменьшение и увеличение занимают одинаковое количество времени, преимущество в том, что сравнение с нулем происходит очень быстро по сравнению со сравнением с переменной. Это верно для многих архитектур, а не только для x86. Что-нибудь с инструкцией JZ (прыгать, если ноль). Обходя вокруг, вы можете найти множество циклов for, которые записаны в обратном направлении, чтобы сохранить циклы при сравнении. Это особенно быстро на x86, так как действие по уменьшению переменной устанавливает соответствующий флаг нуля, так что вы можете затем переходить без необходимости явного сравнения переменной.
  • 20
    Ну, уменьшение до нуля означает, что вам нужно сравнивать только с 0 на каждую итерацию цикла, в то время как итерация к n означает сравнение с n на каждой итерации. Первый способ проще (и на некоторых архитектурах он автоматически тестируется после каждой операции с регистром данных).
Показать ещё 9 комментариев
332
while( x-- > 0 )

как это анализируется.

295

Полностью выродка, но я буду использовать это:

#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;
}
  • 300
    Я надеюсь, что я никогда не сталкивался с вашим исходным кодом ...
  • 53
    @ Mk12 Это не исходный код ... это иероглифы :-)
Показать ещё 3 комментария
277

Одна книга, которую я прочитал (я не помню, правильно, какую книгу) заявил: Компиляторы пытаются разобрать выражения на самый большой токен, используя правило left right.

В этом случае выражение:

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

Надеюсь, это поможет понять сложное выражение ^^

  • 93
    Ваше второе объяснение неверно. Компилятор увидит a-----b и подумает (a--)-- - b , что не компилируется, потому что a-- не возвращает lvalue.
  • 20
    Кроме того, x и -- это два отдельных токена.
Показать ещё 7 комментариев
246

Это точно так же, как

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

для неотрицательных чисел

  • 134
    Разве это не должно быть for(--x++;--x;++x--) ?
  • 8
    @DoctorT для unsigned
Показать ещё 2 комментария
235

В любом случае у нас теперь есть оператор "идет". "-->" легко запомнить как направление, а "while x обращается в нуль" означает "прямолинейно".

Кроме того, он немного эффективнее, чем "for (x = 10; x > 0; x --)" на некоторых платформах.

  • 14
    Идет не может быть правдой всегда, особенно когда значение х является отрицательным.
  • 14
    Другая версия не делает то же самое - с for (size_t x=10; x-->0; ) тело цикла выполняется с 9,8, .., 0, тогда как другая версия имеет 10,9, .., 1. В противном случае выйти из цикла с нуля с помощью переменной без знака довольно сложно.
Показать ещё 6 комментариев
216

Этот код сначала сравнивает 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
160

Мой компилятор распечатает 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;
}

- это другой способ написать одно и то же.

Приятно, что оригинал выглядит как "while x переходит в 0".

  • 4
    Результат не определен, только если вы увеличиваете / уменьшаете одну и ту же переменную более одного раза в одном выражении. Это не относится к этой ситуации.
  • 10
    while( x-- > 0 ) actually means while( x > 0) - я не уверен, что вы пытались сказать там, но то, как вы это сформулировали, подразумевает -- имеет никакого значения, что, очевидно, очень неправильно ,
139

Между -- и > пробел отсутствует. x пост декрементируется, т.е. уменьшается после проверки условия x>0 ?.

  • 39
    Пробел не пропущен - C (++) игнорирует пробел.
  • 27
    @ H2CO3 Это не совсем так. Есть места, где пробелы должны использоваться для разделения токенов, например, в #define foo() против #define foo () .
Показать ещё 1 комментарий
124

-- - оператор декремент, а > - оператор больше.

Два оператора применяются как один, например -->.

  • 7
    Они применяются как 2 отдельных оператора. Они только написаны обманчиво выглядеть как «один один».
122

Это комбинация двух операторов. Первый -- предназначен для уменьшения значения, а > - для проверки того, больше ли значение, чем правый операнд.

#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            
112

Фактически, x пост-декрементируется и проверяется это условие. Это не -->, it (x--) > 0

Примечание: значение x изменяется после проверки условия, поскольку оно пост-декрементируется. Некоторые аналогичные случаи также могут иметь место, например:

-->    x-->0
++>    x++>0
-->=   x-->=0
++>=   x++>=0
  • 5
    За исключением того, что ++> вряд ли можно использовать в какое-то время (). Оператор "идет до ..." будет ++ <, что выглядит не очень хорошо. Оператор -> это счастливое совпадение.
  • 0
    Может ли while (0 <-- x) также работать, тогда?
Показать ещё 1 комментарий
110

C и C++ подчиняются правилу "максимум munch". Точно так же, как --- b переводится на (a--) - b, в вашем случае x-->0 переводится на (x--)>0.

То, что правило гласит по существу, состоит в том, что движение слева направо, выражения формируются путем принятия максимума символов, которые будут формировать правильное выражение.

  • 5
    Это то, что предположил ФП: «((a) ->)» был максимальным глотком. Оказывается, исходное предположение ОП было неверным: «->» не является максимально допустимым оператором.
  • 4
    Также известен как жадный разбор, если я правильно помню.
Показать ещё 1 комментарий
23

Почему все осложнения?

Простой ответ на исходный вопрос:

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

Делает то же самое. Не говоря, что вы должны делать это так, но он делает то же самое и ответил бы на один вопрос.

x-- является только сокращением для выше, а > является просто нормальным более x-- operator. Нет большой тайны!

Там слишком много людей, делающих простые вещи сложными в настоящее время;)

  • 14
    Этот вопрос не о сложностях, а о ** скрытых особенностях и темных углах C ++ / STL **
  • 13
    Программа здесь дает другой вывод, чем оригинальный, потому что x здесь уменьшается после printf. Это хорошо демонстрирует, как «простые ответы» обычно неверны.
Показать ещё 2 комментария
19

В обычном способе мы определяем условие в скобках цикла "()" и условие завершения внутри фигурных скобок "{}", но это -- и > - это способ, которым каждый определяет все сразу. Например, например:

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

Он говорит, уменьшает a и запускает цикл до тех пор, пока время a больше, чем 0

Другим способом это должно было быть:

int abc(){
    int a = 5
    while(a > 0){
        // Code
        a = a -1 // Decrement inside loop
    }
}

в обоих направлениях, мы делаем то же самое и достигаем тех же целей.

  • 4
    Это неверно Код в вопросе: «test-write-execute» (сначала протестируйте, запишите новое значение, выполните цикл), ваш пример - «test-execute-write».
0

C/C++ игнорирует пробелы с условием. По сути, код

while (x --> 0)

это то же самое, что и

while (x-- > 0)

или

while(x > 0){
   x = x - 1
...

Используя пост-декремент в условии. Пусть говорят x = 10. Оператор условия будет равен 10>0 и printf("%d ", x); оператор в цикле даст 9 в первом прогоне. Для второго запуска условие будет 9>0 а печать будет равна 8 и так далее до условия 0>0.

0

Если вы должны были написать функцию, чтобы сделать обратный, синтаксис гораздо более очевидный, не говоря уже о том, что я не думаю, что видел его раньше:

    #include <stdio.h>
    int main()
    {
        int x {10}; while (x ++< 20) // x increments to 20
        {
            printf("%d ", x);
        }
    }

Результат:

11 12 13 14 15 16 17 18 19 20

-2

--> - это в основном то же самое, что:

 for(x=10; x<1; ++x)
    cout<<x

вы находите все числа между x и заданным числом.

-4

На самом деле → не один оператор. Это комбинация двух отдельных операторов - и >

Давайте рассмотрим пример. В то время как (х → 0) Это одно конфиденциальное выражение с одним подтверждением. Здесь первый x является декрементом с его значением, а затем сравнивается с 0.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню