LINUX.ORG.RU

Цикл по всем возможным значениям

 


0

1

Как в Си перебрать все значения от a до b, где 0 <= a < b <= 255, используя 8-битный итератор?

Вопрос возник в связи с написанием конвертера кода из паскаля в Си. В самом паскале пишешь просто

var i: byte;
...
for i:= 0 to 255 do
, а прямой перевод на Си не прокатывает:
for(uint8 i = 0; i <= 255; ++i)

★★★★★
Ответ на: комментарий от unC0Rr

Понял. Никогда об этом не задумывался ;) Прикольно.

adzeitor
()

int iterator;
for (iterator = 0; iterator < 256; iterator++)
{
uint8 i = (uint8) iterator;
...
}

Slavaz ★★★★★
()

прямой перевод на Си не прокатывает

Это у вас С++, а не С.

Я подозреваю, что компилятор Паскаля не совсем честен. Подизассемблируйте и посмотрите как он это делает.

Relan ★★★★★
()

Можно попробовать так сделать:

for(uinsigned char i = 0; i < 128; ++i)
{
   foo(i * 2 + 0);
   foo(i * 2 + 1);
}

andreyu ★★★★★
()
Ответ на: комментарий от geladil

а, черт, так единица пропадет. Ну, можно после второго if сделать повторение [...], но это уже какой-то дикий быдлокод, проще уже одну итерацию поставить до цикла. Хотя и это некрасиво.

geladil
()
Ответ на: комментарий от geekless

Черт, а ведь действительно так. Ловко, спасибо.

geladil
()
Ответ на: комментарий от geekless

Неплохо, но a и b в общем случае заранее неизвестны (возвращаются функциями), как быть в таком случае?

unC0Rr ★★★★★
() автор топика
Ответ на: комментарий от andreyu

Блин, первая проверка пройдёт же до входа в цикл, и оно отинкрементируется. Точно. Тогда годится только тот вариант, что я выше привёл.

geekless ★★
()

Посмотрите на:

#include <limits.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("CHAR_MAX == %d\n", CHAR_MAX);
    return 0;
}

Вывод:

CHAR_MAX == 127

А вообще - надёжнее дождаться переполнения разрядной сетки:

for ( int i = 1; i != 0; i++ ) { ... } // тут можно подставить char, short итд...

KennyMinigun ★★★★★
()
Ответ на: комментарий от unC0Rr

a и b в общем случае заранее неизвестны (возвращаются функциями)

uint8 i = a; 
do 
    { 
     ... 
     i++; 
    } 
while (i != b + 1);

В этом случае всегда будет исполняться строго от a до b, т.е. если b < a, прокрутит через переполнение. Если нужно недопускать такие случаи, придётся еще в блок if (b>=a) {} всё это засунуть.

geekless ★★
()
Ответ на: комментарий от hippi90

И где же здесь С++?

Пардон, С99 допускает такое объявление счетчика.

Relan ★★★★★
()
Ответ на: комментарий от Bad_ptr

Фигово тем, что есть привязка к тому факту, что когда i == 255, то (++i) == 0. Мы же заранее не знаем, что ограничение сверху будет 255 (см. комментарии ТС в треде). Имхо надо что-то вроде

uint8 i=a;
do{
    ....
    if (i == b) break;
} while (1)

Kiborg ★★★
()
Ответ на: комментарий от Bad_ptr

А, вон geekless выше уже привел вариант получше.

Kiborg ★★★
()
Ответ на: комментарий от geladil

Не, у вас не будет итерации при i == 255. Но можно переписать так:

uint8 i = 0; 
do 
    { 
     ... 
     i++; 
    } 
while (i);
Relan ★★★★★
()
Ответ на: комментарий от unC0Rr

Всё-таки паскаль более высокоуровневый, чем си.

спасибокэп.jpg

nanoolinux ★★★★
()
Ответ на: комментарий от Relan

В for счетчик 32 разряда всегда, по барабану какого там размера переменная.

А вот

var
i : BYTE;
begin
i:=0;
while(i<=255) do
begin
Inc(i);
end;

Честно виснет.

ilovewindows ★★★★★
()
Ответ на: комментарий от aol

в _Си_ нельзя определять переменные так.

Вы на свет что ли лезете?

6.8.5.3 The for statement

The statement

for ( clause-1 ; expression-2 ; expression-3 ) statement

behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any variables it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression. If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression.
geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от unC0Rr

Скорее у разработчиков gcc больное самолюбие, по асму видно, что сразу бесконечный цикл генерится, не проверяется счетчик вообще. Могли бы и предупреждение сделать, если уж знают о возможной ошибке.

ilovewindows ★★★★★
()
Ответ на: комментарий от unC0Rr

Может и в языке, может и gcc ни при чём. Мне непонятно упорное стремление программистов сделать косяк на ровном месте. Как будто последнюю минуту живут и другого шанса накосячить не будет.

ilovewindows ★★★★★
()
Ответ на: комментарий от Relan

C99 позволяет объявление переменных в инициализации for'а.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.