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

вопрос создан в Mon, Feb 13, 2017 12:00 AM

После прочтения скрытых функций и темных углов 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. Где это определено в стандарте и откуда оно взялось?

    
8347
  1. Или даже просто правильный интервал ... Я не думаю, что когда-либо видел пробел между переменной и ++ или -- раньше ...
    2009-10-29 07: 09: 47Z
  2. Этот оператор "идет" может быть отменен (0 < - x). Также есть оператор «бежит к» (0 < ---- x). Боже, самая забавная вещь, которую я когда-либо слышал о синтаксисе c ++ =) +1 за вопрос.
    2009-10-29 07: 27: 21Z
  3. Как ни странно, хотя интерпретация очень неправильная, она описывает, что код делает правильно. :)
    2009-11-11 13: 51: 39Z
  4. Представьте себе новые возможности синтаксиса: #define upto ++<, #define downto -->. Если вы чувствуете зло, вы можете сделать #define for while( и #define do ) {#define done ;}) и написать for x downto 0 do printf("%d\n", x) done О, человечество ...
    2010-03-04 07: 07: 25Z
  5. Открывает возможность совершенно нового выразительного способа кодирования, который стоит пожертвовать несколькими предупреждениями компилятора для: bool CheckNegative (int x) {return x < 0? верно :-( неверно); }
    2012-05-28 11: 12: 58Z
21 ответ                              21                         

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

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

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

 
while( (x--) > 0 )
    
8030
2018-12-23 15: 46: 05Z
  1. С другой стороны, в этом контексте он действительно выглядит как некий оператор диапазона.
    2009-10-29 07: 14: 52Z
  2. Сказать, что x пост-уменьшен, а затем сравнивается с 0, то же самое, что сказать, что x уменьшается после сравнения с 0
    2009-10-29 08: 35: 27Z
  3. Я не думаю, что это то же самое. Я думаю, что слово «затем» подразумевает, что есть порядок (после пост-убывания значение х становится на единицу меньше). Я думаю, что можно сказать «Вы отправляете убывание x, а затем сравниваете его старое значение и 0 ...», чтобы сделать его более понятным. Но это все равно придирки. Мы все знаем, что имеется в виду.
    2010-01-30 17: 42: 40Z
  4. В Java он также компилируется:)
    2013-02-12 08: 07: 27Z
  5. Имя для этого @Jay - плохой стиль программирования :-) Об этом свидетельствует тот факт, что вопрос был задан в первую очередь. Гораздо больше смысла в текстовом связывании операторов с тем, над чем они работают, чем с чем-то несвязанным, поэтому while (x-- > 0) будет более подходящим. Это также делает более очевидным, что происходит (по крайней мере, в редакторе с фиксированным шрифтом), означая, что круглые скобки в этом ответе не будутбыть необходимым.
    2016-02-15 01: 28: 00Z

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

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

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

    
2771
2018-10-09 06: 55: 47Z
  1. Извините, но я этого не понимаю. Как это работает?
    2012-03-07 10: 48: 26Z
  2. @ mafutrct - насколько я помню \in C просто добавляет следующую строку, как будто не было разрыва строки. \S здесь в основном ничего не делают.
    2012-03-10 04: 37: 36Z
  3. IIRC, K & RC допускает пробел между '- в операторе декремента, и в этом случае вы можете иметь обратную косую черту в середине, что будет выглядеть еще круче. :)
    2013-07-13 09: 23: 17Z
  4. @ ArnavBorborah это старое выражение, означающее why waste words when a picture does a better job, используемое в этом контексте как шутка. (фактически есть 2 ключевых слова while и printf)
    2016-09-10 11: 36: 46Z
  5. Ах да, неясный оператор слайдов. Как я мог забыть!
    2017-10-27 10: 00: 48Z

Это очень сложный оператор, поэтому даже JTC1 ISO /IEC (Объединенный технический комитет 1) поместил его описание в две разные части стандарта C ++.

Если не считать шутки, это два разных оператора: -- и >, описанные соответственно в §5.2.6 /2 и §5.9 стандарта C ++ 03.

    
2301
2017-03-02 06: 49: 17Z

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

 
while (x-- > 0)

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

 
while(x > 0) {
    x = x-1;
    // logic
}
    
1219
2018-11-06 17: 27: 12Z
  1. Это не совсем верно. Значение x внутри тела цикла отличается во втором случае. Оператор присваивания в вашем примере должен быть над логикой, чтобы он был эквивалентным. Postfix - вычитает 1, но сравнение будет происходить со значением от до вычитания.
    2018-10-16 16: 03: 48Z
  2. @ uliwitness Они действительно эквивалентны. Было бы неправильно, если бы использовался префикс: 0 >-- x В этом случае x уменьшается до логики. В постфиксе логика выполняется перед уменьшением, и, таким образом, оба образца эквивалентны. Не стесняйтесь записывать их в Console и тестировать их.
    2019-01-02 19: 36: 20Z
  3. Они все еще не эквивалентны. После первого цикла x равен -1 (или переполнен в случае, если он не подписан), после второго он равен 0. (Если исходить из того, что x начинается неотрицательно, ни один цикл не изменяет x или не прерывается или…)
    2019-01-15 14: 56: 57Z

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

;) р>     

1049
2017-10-11 02: 51: 48Z
  1. в какой операционной системе сгенерирован этот тип вывода, я использую Ubuntu 12.04, в котором у меня было сообщение об ошибке
    2015-01-19 12: 13: 36Z
  2. Хотя это должно быть очевидно, для всех новичков в C ++ читающих это: не делайте этого. Просто используйте расширенное назначение, если вам нужно увеличить /уменьшить более чем на один.
    2015-03-26 02: 41: 40Z
  3. Ноль с "лазерами". while (0 > - - - - - - - - - - ---------- x) ... тот же вывод.
    2016-03-09 21: 54: 16Z
  4. @ phord вы уверены, что он не компилируется? - &GT; coliru.stacked-crooked.com/a/5aa89a65e3a86c98
    2016-03-24 10: 43: 16Z
  5. @ doc Компилируется в c ++, но не в c.
    2016-03-25 14: 58: 46Z

Это

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

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

       printf("%d ", x);
     }

     return 0;
}

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

    
528
2018-03-08 17: 02: 25Z

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

    
398
2009-11-18 12: 47: 41Z
  1. Не совсем верно. Уменьшение и увеличение занимают одинаковое количество времени, преимущество в том, что сравнение с нулем происходит очень быстро по сравнению со сравнением с переменной. Это верно для многих архитектур, а не только для x86. Что-нибудь с инструкцией JZ (прыгать, если ноль). В поисках вы можете найти множество циклов for, которые записаны в обратном направлении, чтобы сохранить циклы при сравнении. Это особенно быстро происходит в x86, поскольку при уменьшении переменной устанавливается соответствующий флаг нуля, поэтому вы можете переходить без необходимости явно сравнивать переменную.
    2009-12-30 05: 16: 46Z
  2. Ну, уменьшение до нуля означает, что вам нужно сравнивать только с 0 для каждой итерации цикла, а итерация к n означает сравнение с n для каждой итерации. Первый способ проще (и на некоторых архитектурах он автоматически тестируется после каждой операции с регистром данных).
    2010-04-12 15: 07: 58Z
  3. @ burrito Хотя я не согласен, циклы, обусловленные ненулевыми значениями, обычно предсказываются почти идеально.
    2014-01-11 09: 05: 12Z
  4. Увеличение и уменьшение одинаково быстро, вероятно, на всех платформах (определенно на x86). Разница заключается в тестировании условия окончания цикла. Чтобы увидеть, достиг ли счетчик нуля, он практически свободен - когда вы уменьшаете значение, в процессоре устанавливается нулевой флаг, и для определения конечного условия вам просто нужно проверить этот флаг, тогда как при увеличении требуется операция сравнения перед конечным условием. может быть обнаружен.
    2015-02-18 11: 14: 01Z
  5. Конечно, все это в наши дни неактуально, поскольку современные компиляторы могут векторизоватьи обратный цикл автоматически.
    2015-02-20 03: 53: 56Z
 
while( x-- > 0 )

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

    
345
2009-11-19 19: 46: 56Z

Совершенно отвратительный, но я буду использовать это:

 
#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;
}
    
333
2011-12-03 02: 33: 05Z
  1. Я надеюсь, что никогда не сталкивался с вашим исходным кодом ...
    2012-08-15 01: 44: 31Z
  2. @ Mk12 Это не исходный код ... это иероглифы: -)
    2012-09-07 03: 27: 35Z
  3. @ SAFX - это было бы совершенно иероглифически с египетские скобки
    2012-11-14 10: 00: 02Z
  4. Это не компилируется. C не Паскаль, где внутренняя часть do ... while является списком выписок. В C это блок, поэтому он должен быть do { ... } while.
    2016-09-11 02: 20: 23Z
  5. @ EJP компилируется. Синтаксис do statement while ( expression ) ;. Сказав это, я надеюсь, что это понято, я имел в виду пример как шутку.
    2016-10-18 17: 28: 10Z

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

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

 
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

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

    
304
2015-04-23 09: 02: 58Z
  1. Ваше второе объяснение неверно. Компилятор увидит a-----b и подумает (a--)-- - b, который не компилируется, потому что a-- не возвращает lvalue.
    2010-05-05 15: 26: 03Z
  2. Кроме того, x и -- - это два отдельных токена.
    2010-07-02 19: 20: 05Z
  3. Это известно как Максимальный жаворонок .
    2014-03-13 11: 09: 26Z
  4. @ DoctorT: он передает лексер. Только семантический проход способен испустить эту ошибку. поэтому его объяснения верны.
    2014-09-01 03: 34: 53Z
  5. Пока вы думаете, что --> является оператором (что подразумевается под вопросом, который был задан), этот ответ не поможет вообще - вы думаю, что токен 2 - это -->, а не только --. Если вы знаете, что --> не оператор, у вас, вероятно, нет проблем с пониманием кода в вопросе, поэтому, если у вас нет совершенно другого вопроса, я не совсем уверен, как это может быть полезно.
    2015-05-22 12: 33: 43Z

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

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

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

    
253
2015-04-30 22: 48: 34Z
  1. Разве это не должно быть for(--x++;--x;++x--)?
    2011-12-04 21: 32: 19Z
  2. @ DoctorT - это то, для чего предназначен unsigned
    2013-03-23 ​​18: 39: 13Z
  3. @ MateenUlhaq, что неправильно в соответствии со стандартом, выражение --x++ имеет неопределенное поведение в соответствии с §1.9.15
    2015-06-19 02: 02: 01Z
  4. Если бы он использовал unsigned, он бы использовал %u
    2019-02-21 22: 01: 27Z

В любом случае, у нас теперь есть оператор "идет". "-->" легко запомнить как направление, и «пока х уходит в ноль» - это прямое значение.

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

    
230
2013-02-28 17: 28: 13Z
  1. Идет не может быть истиной всегда, особенно когда значение x отрицательно.
    2009-11-13 03: 22: 41Z
  2. Другая версия не делает то же самое - с for (size_t x=10; x-->0; ) тело цикла выполняется с 9,8, .., 0, тогда как другая версия имеет 10, 9, .., 1. В противном случае выйти из цикла с нуля с помощью переменной без знака довольно сложно.
    2010-06-21 08: 57: 44Z
  3. Я думаю, что это немного вводит в заблуждение ... У нас нет буквального оператора "идет в", так как нам нужен еще ++> для выполнения добавочной работы.
    2013-06-15 02: 49: 10Z
  4. @ Джош: на самом деле, переполнение дает неопределенное поведение для int, поэтому она может так же легко съесть вашу собаку, как и взять x в ноль, если она начнет отрицательно.
    2013-12-06 06: 57: 56Z
  5. Это очень важная для меня идиома по причине, указанной в comnmet @PeteKirkham, так как мне часто приходится делать убывающие циклы для неподписанных величин вплоть до 0 , (Для сравнения, идиома пропуска тестов на ноль, например, написание while (n--) вместо для беззнакового n, ничего не покупает, и для меня сильно затрудняет читабельность.) Он также имеет приятное свойство, которое вы указываете еще один чем начальный индекс, который обычно является тем, что вы хотите (например, для цикла над массивом вы указываете его размер). Мне также нравится --> без пробела, так как это облегчает распознавание идиомы.
    2014-08-30 20: 08: 39Z

Этот код сначала сравнивает 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
    
212
2016-01-03 17: 48: 14Z

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

    
167
2015-04-30 22: 49: 12Z
  1. Результат не определен, только если вы увеличиваете /уменьшаете одну и ту же переменную более одного раза в одном выражении. Это не относится к этой ситуации.
    2010-05-05 15: 30: 19Z
  2. while( x-- > 0 ) actually means while( x > 0) - я не уверен, что вы пытались сказать там, но то, как вы это сформулировали, подразумевает, что -- не имеет никакого значения, что, очевидно, очень неправильно.
    2015-05-22 12: 28: 30Z

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

    
138
2010-11-22 19: 02: 21Z
  1. Пробел не пропущен - C (++) игнорирует пробел.
    2012-08-02 19: 16: 31Z
  2. @ H2CO3 В целом это не так. Есть места, где пробел должен использоваться для разделения токенов, например, в #define foo() против #define foo ().
    2013-04-25 21: 16: 44Z
  3. @ Jens Как насчет: "Пробел не пропущен - C (++) игнорирует ненужный пробел."?
    2013-12-04 20: 35: 14Z

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

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

    
129
2011-10-29 21: 42: 06Z
  1. Они применяются как два отдельных оператора, которыми они являются. Они только написаны , вводя в заблуждение, чтобы выглядеть как «один».
    2016-11-12 17: 56: 09Z

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

 
#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            
    
123
2015-04-30 22: 50: 01Z

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

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

 
-->    x-->0
++>    x++>0
-->=   x-->=0
++>=   x++>=0
    
117
2014-04-12 09: 52: 33Z
  1. Кроме этого ++ > вряд ли можно использовать какое-то время (). Оператор "идет до ..." был бы ++ &lt ;, который выглядит не очень хорошо. Оператор - > это счастливое совпадение.
    2014-09-01 09: 46: 25Z
  2. Может ли while (0 <-- x) также работать, тогда?
    2015-06-15 14: 00: 33Z
  3. @ BenLeggiero Это может «сработать» в смысле генерации кода, который делает что-то (в то же время приводя в бешенство читателей, которые не любят ложно-умный код), но семантика отличается, так как его использование precrement означает, что он выполнит еще одну итерацию. В качестве надуманного примера, он никогда не будет выполнять тело цикла, если x начнется с 1, а while ( (x--) > 0 ) будет. {edit} Эрик Липперт рассказал обо всех своих заметках о выпуске C # 4: blogs.msdn.microsoft.com/ericlippert/2010/04/01/…
    2016-11-12 17: 57: 29Z

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

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

    
113
2014-04-12 09: 55: 16Z
  1. Это то, что предположил OP: этот "((a) - >)" был максимальным хламом. Оказывается, исходное предположение ОП было неверным: "- >" не является максимально допустимым оператором.
    2014-08-28 00: 41: 45Z
  2. Также известен как жадный синтаксический анализ, если я правильно помню.
    2015-07-11 01: 04: 15Z
  3. @ RoyTinker Жадное сканирование. Парсер не имеет к этому никакого отношения.
    2016-09-11 02: 21: 50Z

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

Простой ответ на оригинальный вопрос:

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

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

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

В наши дни слишком много людей делают сложные вещи сложными;)

    
26
2018-06-30 10: 10: 56Z
  1. Этот вопрос не о сложностях, а о ** скрытых возможностях и темных углах C ++ /STL **
    2016-10-27 15: 32: 01Z
  2. Программа здесь выдает выходные данные, отличные от оригинала, потому что здесь x уменьшается после printf. Это хорошо демонстрирует, как «простые ответы» обычно неверны.
    2017-05-13 09: 30: 30Z
  3. The OP's way: 9 8 7 6 5 4 3 2 1 0 и The Garry_G way: 10 9 8 7 6 5 4 3 2 1
    2017-12-15 18: 33: 22Z
  4. Это не делает то же самое. Переместите свой x=x-1 до printf, тогда вы можете сказать, что «он делает то же самое».
    2019-01-05 17: 05: 49Z

Традиционным образом мы определяем условие в скобках 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--;
}

В обоих случаях мы делаем одно и то же и достигаем одинаковых целей.

    
23
2019-06-15 19: 35: 13Z
  1. Это неверно. Код в вопросе: «test-write-execute» (сначала протестируйте, запишите новое значение, выполните цикл), ваш пример - «test-execute-write».
    2017-07-14 19: 07: 40Z
  2. @ v010dya Исправлен ответ, теперь это test-write-execute, как в вопросе, спасибо за указание!
    2019-05-12 10: 59: 49Z
  3. @ VladislavToncharov Ваша правка по-прежнему неверна. Смотри мой.
    2019-06-15 19: 36: 17Z
источник размещен Вот