У меня есть программа, которую я пытаюсь расшифровать. Он переведен на C с другого языка ( имя которого здесь не указано ), и поскольку я хочу понять, как это работает, я медленно переписываю код и упрощаю его, чтобы использовать все полезные логические конструкции, которые C может предложить.
Следующий маленький бит продолжает появляться в моем коде с различными значениями X
и Y
:
ptr[X]--; while(ptr[X]) { ptr[X]--; ptr += Y; }
вptr[X]--; while(ptr[X]) { ptr[X]--; ptr += Y; }
ptr
имеет тип char *
, и я не могу действительно делать предположения о состоянии массива в любой точке, потому что он довольно глубоко внедрен в петли и зависит от ввода и вывода. Я могу успешно «упростить», чтобы:
for(ptr[X]--; ptr[X]; ptr[X]--, ptr += Y);
Но это просто ужасно. С таким чуть-чуть лучше:
for(ptr[X]--; ptr[X]; ptr += Y) ptr[X]--;
Я хочу знать, может ли кто-нибудь придумать лучшее упрощение вышеуказанного кода, я был бы очень признателен. Это происходит не менее чем в пяти местах, и это ухудшает мою способность упрощать и понимать управление streamом, поэтому, если кто-то может предоставить более понятную / удобочитаемую версию, это будет потрясающе. Если кто-то может просто предложить какое-то причудливое понимание этого кода, это тоже будет потрясающе, хотя я в основном понимаю, что он делает.
Также может помочь понимание кода для конкретного X
и / или Y
Y
имеет тенденцию быть между -2 и 2, а X
обычно 1, для чего его стоит.
ptr[X]
эквивалентно *(ptr + X)
, поэтому мы можем переписать его следующим образом:
for((*(ptr + X))--; *(ptr + X); (*(ptr + X))--, ptr += Y);
Теперь здесь много избыточности, поэтому мы можем упростить это:
char *ptr_plus_x = ptr + X; for((*ptr_plus_x)--; *ptr_plus_x; (*ptr_plus_x)--, ptr_plus_x += Y);
Тогда мы можем полностью избавиться от ptr_plus_x
:
ptr += X; for((*ptr)--; *ptr; (*ptr)--, ptr += Y);
На английском языке мы посещаем ячейки памяти в смещениях X, X + Y, X + 2Y, X + 3Y, …, уменьшая каждую ячейку памяти до тех пор, пока не найдем место памяти, равное 0. Но тест для 0 всегда происходит после декремента, поэтому мы действительно ищем первое место памяти в этой последовательности со значением 1. Как только мы найдем это, мы уменьшим его до 0 и прекратим.
Если Y равно 1, то мы уменьшаем строку последовательных мест памяти, идущих вперед, вплоть до первого включительно. Если Y равно -1, происходит то же самое, но выполняется поиск назад от смещения X. Если Y равно 0, петля. Если Y – любое другое значение, шаблон поиска пропускает различные записи.
Это не очень интуитивная функция, поэтому я могу понять, почему вы смущены.
Я заберу:
ptr[X]-- while (ptr[X]--) ptr+=Y;
сначала оценивайте, затем уменьшайте (в то время как условие, то есть)
Edit: Хорошо, я буду ненавидеть себя утром. Гото, все в порядке на этом уровне, не так ли?
dec: ptr[x]-- while (ptr[X]){ ptr+=Y; goto dec; }
(я честно не знаю, оставить это или нет).
EDIT2: так, как насчет этого? (tcc не жаловался)
while (ptr[X]--?ptr[X]--,ptr+=Y:0){}
EDIT 2 1/2;
//longshot while (ptr[X]--?ptr[X]--,ptr+=Y, ptr[X]:0){}
Если все остальное терпит неудачу..
EDIT3: последний на сегодня.
while (ptr[X]--?ptr[X]--,ptr+=Y:0){ if (!ptr[X]) break; }//good luck with this, it has been very amusing.
Веб-сайт для него, который не должен быть назван, гласит:
The semantics of the it-which-shall-not-be-named states commands can also be succinctly expressed in terms of C, as follows (assuming that p has been previously defined as a char*): > becomes ++p; < becomes --p; + becomes ++*p; - becomes --*p; . becomes putchar(*p); , becomes *p = getchar(); [ becomes while (*p) { ] becomes }
Таким образом, кажется, что довольно легко преобразовать его в C.
EDIT: Здесь Hello World BF преобразован в C ++.
Это довольно просто, как есть. Вместо того, чтобы писать меньше заявлений, я скорее попытаюсь понять намерение и добавить комментарий.
Пример значения «a» fragmentа: уменьшите все элементы столбца (X) матрицы из Y столбцов. Вам понадобится, чтобы нарисовать вертикальную линию + ‘ses, например, на языке, который не имеет прямого назначения.
Вы можете прояснить этот смысл, указав индексы напрямую:
// set elements of column to cGoal for( int decrementsToGoal = cGoal; decrementsToGoal != 0; --decrementsToGoal ) { // decrease all elements of column X for( int row = cMaxRows; M[ row*matrixsizeY + columnX ]; --row ) { --M[ row*matrixsizeY + columnX ]; } }
Удачи 🙂