В Java, почему я не могу написать i++++ или (i++)++?

Когда я пытаюсь написать постфикс/префикс в/декременте, за которым следует пост/префикс в/декременте, я получаю следующую ошибку: Недопустимый аргумент для операции ++/--.

Но, согласно JLS:

PostIncrementExpression:
        PostfixExpression ++

и

PostfixExpression:
        Primary
        ExpressionName
        PostIncrementExpression
        PostDecrementExpression

поэтому пишу:

PostfixExpression ++ ++

должно быть возможно... Любые мысли?


person John Assymptoth    schedule 10.01.2011    source источник
comment
Тебе не кажется, что --++----++var++----++--++ может немного сбивать с толку?   -  person Crozin    schedule 11.01.2011
comment
Учитывая, что приращение C++ — это C#, пробовали ли вы использовать i#? ;-)   -  person John Topley    schedule 11.01.2011
comment
@Anon - i++ возвращает значение, а не ссылку... Это мой ответ. :)   -  person John Assymptoth    schedule 11.01.2011
comment
@Crozin - Какая разница, сбивает это с толку или нет. Я создаю метапрограмму, мне нужно знать такие вещи.   -  person John Assymptoth    schedule 11.01.2011
comment
@Woot4Moo - Ой! Да ладно, этот вопрос немного актуален ..   -  person John Assymptoth    schedule 11.01.2011
comment
@ Джон, возможно, если вы сделаете это немного более ясным в вопросе и в заголовке, это сделает гораздо меньше насмешек. Но я удалю это только для вас.   -  person Woot4Moo    schedule 11.01.2011


Ответы (10)


Обратите внимание, что в необработанной грамматике отсутствует какая-либо семантика. Это всего лишь синтаксис, и не каждая синтаксически корректная программа будет корректной. Например, требование о том, что переменные должны быть объявлены перед использованием, обычно не покрывается грамматикой (можно, но это громоздко).

Postfix-increment дает rvalue — и точно так же, как вы не можете постфиксно-инкрементировать литералы, вы не можете постфиксно-инкрементировать результат i++.

Цитата из JLS (3rd изд., стр. 486):

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

person Joey    schedule 10.01.2011
comment
Вы можете закодировать объявление перед использованием в грамматике? Для любого количества любых идентификаторов? - person ; 11.01.2011
comment
@delnan: Да, грамматики Ван Вейнгардена были задуманы для таких вещей. Но для всех практических целей двухуровневые грамматики громоздки, и вы можете добиться того же с помощью простой атрибутивной грамматики, которая определяет утверждения, которые распространяются вниз по AST (если я правильно помню, с тех пор прошло несколько лет). - person Joey; 11.01.2011

Ошибка говорит вам ответ:

unexpected type
required: variable
found   : value
        (i++)++;

Таким образом, i++ оценивается как значение, в то время как оператору требуется переменная.

person JOTN    schedule 10.01.2011
comment
Хм, наверное, зависит от компилятора. EclipseC выдает «Неверный аргумент операции ++/--», что не так полезно. - person Joey; 11.01.2011
comment
Интересный. Да, это не так полезно. Ошибка выше от компилятора Sun. - person JOTN; 11.01.2011

Вы можете применять ++ или -- только к выражению, обозначающему изменяемое местоположение (lvalue). РЕЗУЛЬТАТ ++ или -- - это значение из местоположения (значение r - либо до, либо после увеличения или уменьшения), а не само изменяемое местоположение. Таким образом, вы не можете сказать (a++)++ так же, как вы не можете сказать (a+b)++ — нет места, которое нужно изменить.

person Chris Dodd    schedule 10.01.2011

Проблема с этим выражением i = (i++)++; заключается в том, что (i++) преобразуется в значение, а определение оператора ++ говорит, что 1 . он увеличит указанную переменную и поместит/вернет значение для нее, независимо от того, используете ли вы Postfix или Prefix. 2. Для этого оператора требуется переменная, будь то префикс или постфикс. Но здесь происходит то, что (i++) возвращает значение и помещает его вместо (i++), а затем у вас есть (value)++ и (value) не ожидаемый тип для этого оператора, поскольку он требует переменной вместо значения.

например, в Java, если вы скомпилируете следующий фрагмент кода, вы получите ошибку, как показано после фрагмента:

открытый класс A { public void test () { int i = 0; я = (я++)++; } }

Выход компиляции:

A.java:4: требуется непредвиденный тип: найдена переменная: значение i = (i++)++; ^ 1 ошибка

person Ajay Bhojak    schedule 23.07.2013

i++ в основном является ярлыком для:

(i = i+1)

И нет смысла писать:

(i = i+1)++;

Правильно? :)

person Kylar    schedule 10.01.2011
comment
(i = i + 1) не ведет себя так же, как (i++) - первый возвращает новое значение i, второй возвращает старое. - person Anon.; 11.01.2011
comment
Извини. Думаю, я не выбрал хороший смайлик, который передает шутку. Моя вина. -1 себе за это. - person Kylar; 11.01.2011

Что должно получиться в результате такой операции? Результатом i++ является (копия) текущее значение i, а i впоследствии увеличивается (опубликовать). Итак, как вы представляете себе увеличение результата i++ еще раз? Если i изначально было равно 1, каким должно быть его значение после i++++ и каков должен быть результат этой операции?

Если вы подумаете об этом, вы, вероятно, поймете, что было бы очень правильно определить это. Поскольку разработчики Java намеревались избежать ловушек «неопределенности» C/C++ (и поскольку ценность такого утверждения в лучшем случае сомнительна), они, вероятно, решили явно запретить его.

person Péter Török    schedule 10.01.2011
comment
Нет, не поэтому. Причина, как указано в других ответах, заключается в том, что результатом выражения i++ является значение, а не ссылка, которую можно изменить. - person John Assymptoth; 11.01.2011
comment
Я вспомнил это из-за комментариев/ответов. - person John Assymptoth; 11.01.2011

Обязательно помните: операторы инкремента и декремента (префикс и постфикс) всегда работают с переменной, а не с значением< /эм>

Здесь я объясню это с помощью одного exe:

int i = 0;

int j = (i++)++;

выше exe.

инициализировать значение i 0 (нулем)

в (i++) '++' работает с переменным i и после выполнения операции возвращает (1)

теперь в (1)++ '++' работает с (1), которое является значением, а не переменной, что противоречит правилам java, поэтому ошибка времени компиляции генерирует Недопустимый аргумент для операции ++ /--

person Dhruv Raval    schedule 06.04.2015

Чего вы пытаетесь достичь с помощью (i++)++?

увеличьте его в два раза!!

Использовать зацикливание

Увеличение внутри цикла :)

person zod    schedule 10.01.2011
comment
Угу. Конечно, i+=2 лучше, чем цикл. - person Stephen C; 11.01.2011

В i++ ++ является постфиксным оператором, поэтому он возвращает значение i, а затем увеличивает его. Что бы вы хотели, чтобы (i++)++ делал? Должен ли он возвращать i+1, так как (i++ == i)? Если нет, то не было бы странно, что i++=i, но (i++)++ != i) рассмотрим следующие выражения:

i++  ==  i;   // true
j = i++  // j gets the value of i
j++ == i //  still true since j== i

(i++) ++ ==  j ++    //  what should be the answer here?

Вы рассматривали i+=2?

person Zeki    schedule 10.01.2011

Почему бы вам просто не использовать сокращенный оператор приращения?

i+=2

Там.

person Jeshurun    schedule 13.07.2011