Подтвердить что ты не робот

Как инициализировать несколько переменных в цикле for (;;) в C?

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

for (int i = 0, char* ptr = bam; i < 10; i++) { ... }

Но я только выяснил, что это невозможно, gcc дает следующую ошибку:

error: expected unqualified-id before 'char'

Правда ли, что вы не можете инициализировать переменные разных типов в цикле for?

4b9b3361

Ответ 1

Вы можете (но обычно не должны) использовать локальный тип структуры.

for ( struct { int i; char* ptr; } loopy = { 0, bam };
      loopy.i < 10 && * loopy.ptr != 0;
      ++ loopy.i, ++ loopy.ptr )
    { ... }

Так как С++ 11, вы можете более элегантно инициализировать отдельные части, если они не зависят от локальной переменной:

for ( struct { int i = 0; std::string status; } loop;
      loop.status != "done"; ++ loop.i )
    { ... }

Это достаточно читаемо, чтобы действительно использовать.


С++ 17 планируется решить проблему со структурированными привязками:

for ( auto [ i, status ] = { 0, ""s }; status != "done"; ++ i )

Однако подробный набор функций и синтаксис все еще находятся в движении.

Ответ 2

Верно, что вы не можете одновременно объявлять и инициализировать деклараторы разных типов. Но это не относится к циклам. Вы получите сообщение об ошибке:

int i = 0, char *ptr = bam;

тоже. Первое предложение цикла for может быть (C99 §6.8.5.3) "декларацией" или "недействительным выражением". Обратите внимание, что вы можете сделать:

int i = 0, *j = NULL;
for(int i = 0, *j = NULL;;){}

потому что i и *j являются типами int. Точный синтаксис объявления приведен в §6.7.

Ответ 3

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

{ char* ptr = bam; for (int i = 0; i < 10; i++) { ... } }

Это немного уродливо, но работает.

Ответ 4

попробуйте следующее:

int i;
char* ptr;
for (i = 0, ptr = bam; i < 10; i++) { ... }

Ответ 5

В соответствии с http://linuxsoftware.co.nz/cppgrammar.html#for-init-statement вы можете получить только простую декларацию или выражение (которое не разрешено содержать объявление) в for- init. Это означает, что ответ отрицательный (если я правильно проанализировал BNF:))

Ответ 6

Я думаю, что языки, которые они учат вас, дети в эти дни, предназначены для наручника и гнили вашего мозга, чтобы вы просто успокоились и поместили блоки lego в очень ограниченную форму, в которой они предназначены, чтобы объединиться, чтобы вы стали посредственными вещи. Красота C заключается в том, что вы можете следовать правилам и умело, чтобы получить то, что вы хотите. Вот как вы пишете этот цикл с дополнительными инициализаторами. Вот рабочий пример, который показывает вам, как переместить расширенный цикл на первый. Вы используете первое для пиратства своих переменных, и они остаются в сфере видимости. Вы используете фиктивную переменную, чтобы заставить внешний цикл работать один раз. Умный компилятор будет замечать факт и nuke цикл с циклом. Так что для вас это просто польза. Второй массив затем использует некоторые переменные из первого объявления и второго объявления и заканчивается. Это тривиальный пример, который просто означал, что вы сможете понять, как это сделать без тяжелого движения броска в некоторых областях. Поскольку этот метод можно использовать с макросами при написании так, чтобы создать красивое следующее поколение, такое как перечисление структуры, например "для значения в массиве", из которых у меня много.

#include "stdio.h"
int
main(int argc, char **argv)
{
    const int max=7;
    const char *array[7] = {
    "hello","you","kids","who","don't","know","malloc\n"
    };

    for(int i=0,count=max,$=1;$;$=0)
    for(const char **p=array;count<max;i++)
    {
        printf("%s ",p[i]);
    }
}

Здесь ничего не пропало. Этот метод для объединения цикла с одним кадром для цикла использовался для встраивания в вызов для получения перечислителя для этого хеш-объекта и начала перечисления, для получения значений, извлеченных для ключа и значения, а также путем удобного создания они как указатели void для пользователя, он просто должен их назвать. Затем они заполняются, и перечисление будет продолжаться до тех пор, пока не будут выполнены все ключи и значения. Если пользователь разбивается на итерацию, весь каскад из этих ловушек будет разваливаться по мере того, как мы захотим, потому что они, вероятно, даже не существуют, поскольку они были созданы с помощью простых const ops, которые может видеть компилятор, разворачивают цикл. Таким образом, в основном это позволяет вам расширять синтаксис, чтобы делать такие вещи без штрафа.

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