В C ++ почему я не могу написать цикл for () следующим образом: for (int i = 1, double i2 = 0; - PullRequest
20 голосов
/ 26 июля 2010

или, «Объявление нескольких переменных в цикле for ist verboten»?!

Мой исходный код был

 for( int i = 1, int i2 = 1; 
      i2 < mid;
      i++, i2 = i * i ) {

Я хотел перебрать первые так много квадратов, ихотел и число и его квадрат, и условие остановки зависело от квадрата.Этот код кажется наиболее чистым выражением намерения, но он недействителен.Я могу придумать дюжину способов обойти это, поэтому я не ищу лучшую альтернативу, но для более глубокого понимания того, почему это неверно.Немного языковой адвокатуры, если хотите.

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

for( int i = 0; ....

синтаксис.Чтение вокруг выглядит так, как будто вы можете иметь только одно объявление типа в первом разделе оператора for ().Таким образом, вы можете сделать

for( int i=0, j=0; ...

или даже слегка барокко

for( int i=0, *j=&i; ...

, но не очень разумный

for( int i=0, double x=0.0; ...

Кто-нибудь знает почему?Это ограничение для ()?Или ограничение на списки запятых, например, «первый элемент списка запятых может объявлять тип, но не другой? Является ли следующее использование запятых различными синтаксическими элементами C ++?

(A)

for( int i=0, j=0; ...

(B)

int i = 0, j = 0;

(C)

 int z;
 z = 1, 3, 4;

Есть ли здесь гуру?

==========================================================

На основена хороших ответах, которые я получил, я думаю, что могу уточнить вопрос:

В заявлении for

for( X; Y; Z;) {..... }

Что такое X, Y и Z?

Мой вопрос был о C ++, но у меня нет большой ссылки на C ++. В моей ссылке на C (Harbison and Steele 4th ed, 1995) все они представляют собой три выражения , и мой gcc требует режима C99 дляиспользовать для (int i = 0;

В Stroustrup, с. 6.3, синтаксис оператора for задается как

для операторов (for-init-Statement; условие; выражение)

Так что в C ++ есть специальный синтаксический оператор, посвященный первому предложению в for (), и мы можем предположить, что ониесть особые правила, помимо тех, что для выражения.Этот звук действителен?

Ответы [ 7 ]

20 голосов
/ 26 июля 2010

Если вам нужно использовать несколько переменных различного типа в цикле for, вы можете использовать структуры следующим образом:

for( struct {int i; long i2;} x = {1, 1}; x.i2 < mid; x.i++, x.i2 = x.i * x.i )
{
  cout << x.i2 << endl;
}

так что это не ограничение, просто используйте немного другой синтаксис.

16 голосов
/ 26 июля 2010

int i = 1, double i2 = 0; не является допустимым оператором объявления, поэтому его нельзя использовать внутри оператора for.Если оператор не может стоять отдельно от for, то его нельзя использовать внутри оператора for.

Редактировать: По поводу ваших вопросов об операторах запятой, опциях«A» и «B» идентичны и оба действительны.Опция 'C' также действительна, но, вероятно, не будет делать то, что вы ожидаете.z будет присвоено 1, а операторы 3 и 4 на самом деле ничего не сделают (ваш компилятор, вероятно, предупредит вас о "операторах без эффекта" и оптимизирует их).

Обновление: Чтобы ответить на вопросы в вашем редактировании, вот как C ++ spec (Sec 6.5) определяет for:

for ( for-init-statement condition(opt) ; expression(opt) ) statement

Далееопределяет for-init-statement как expression-statement или simple-declarationcondition, и expression являются необязательными.

for-init-statement может быть любым допустимым значением expression-statement (например, i = 0;) или simple-declaration (например, int i = 0;).Оператор int i = 1, double i2 = 0; не является допустимым simple-declaration в соответствии со спецификацией, поэтому его нельзя использовать с for.Для справки, simple-declaration определяется (в разделе 7) как:

attribute-specifier(opt) decl-specifier-seq(opt) init-declarator-list(opt) ;

, где decl-specifier-seq будет типом данных плюс ключевые слова, такие как static или extern и init-declarator-list будутразделенный запятыми список объявлений и их необязательных инициализаторов.Попытка поместить более одного типа данных в один и тот же simple-declaration по существу помещает decl-specifier-seq, где компилятор ожидает init-declarator-list.Неправильный просмотр этого элемента приводит к тому, что компилятор обрабатывает строку как неправильно сформированную.

Спецификация также отмечает, что цикл for эквивалентен:

{
    for-init-statement
    while ( condition ) {
        statement
        expression ;
    }
}

где condition по умолчанию "true", если оно опущено.Размышление об этой «расширенной» форме может помочь определить, можно ли использовать данный синтаксис с циклом for.

13 голосов
/ 26 июля 2010

Это на самом деле ограничение деклараций:

int i=0, j=0, *k=&i;     // legal
int i=0, double x=0.0;   // illegel

Итак, в основном, ответ на ваш последний вопрос: (A) и (B) одинаковы. (С) отличается.

Как указывает bta:

 z = 1,3,4;

совпадает с

 z = 1;

Однако это потому, что = имеет более высокий приоритет, чем ,. Если бы это было написано как:

 z = (1,3,4);

тогда это будет так же, как:

 z = 4;
1 голос
/ 26 июля 2010

Что ж, я сделал еще несколько поисков в Google, и я думаю, что ответ на C ++ - "for () - это очень специальные места".1005 * где

for-init-statement:
expression-statement
simple-declaration

, и они должны указать, что

[Note: a for-init-statement ends with a semicolon. ] 

Так что синтаксис C ++ спец.специально взломан, так что только один decl-spec (то есть тип) разрешен в первом слоте.Похоже, наши попытки спорить с основными принципами были обречены.Спасибо за все ответы.

1 голос
/ 26 июля 2010

C ++ (также C и Java) не разрешают объявление более одного типа переменных в области цикла for. В грамматике это потому, что запятая не начинает новый оператор в этом контексте. Фактически, внутри оператора for(;;) допускается только одно объявление. Это объясняется тем, что это требование довольно необычно, и вы можете получить его только с немного более подробной конструкцией.

1 голос
/ 26 июля 2010

До тех пор, пока вы можете написать действительное утверждение с оператором запятой ,, это приемлемо.

0 голосов
/ 27 июля 2010

Я понимаю, почему вы надеетесь , что это сработает, но - учитывая, что даже при использовании довольно простого обучающего инструмента, который

for (i=0; i<max; i++){
   ...
}

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

i=0;
while (i<max){
   ...
   i++;
}

ваш синтаксис не работает - я не понимаю, почему вы ожидали , что это произойдет.Каждый бит должен быть действительным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...