- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
#include <stdio.h>
int main()
{
int a = 5, b = 6;
void* go;
go = ( a > b )? &&true1: &&false1;
goto *go;
true1:
{
printf("%i > %i\n", a, b);
goto next1;
}
false1:
{
printf("%i <= %i\n", a, b);
}
next1:
a = 7;
go = ( a > b )? &&true2: &&false2;
goto *go;
true2:
{
printf("%i > %i\n", a, b);
goto next2;
}
false2:
{
printf("%i <= %i\n", a, b);
}
next2:
return 0;
}
В GCC есть такой экстеншен http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
Можно в goto передавать переменную и можно работать с адресами меток. В сочетании с тернарной условной операцией, этим можно заменить if
Эта фича существовала давным-давно, еще до ANSI C, когда по земле ходили мамонты... Потом ее слава богу выпилили... Как оказалось - не до конца.
P.S. Тут же можно еще и с адресной арифметикой постебаться - goto go+5;
Это на случай, если на одном из входов затесалась двойка? :)
http://gravatar.com/avatar/f3dd16071dd47ba61cd705ed6d200069?size=512
http://rudocs.exdat.com/pars_docs/tw_refs/33/32904/32904_html_7235efb3.gif
Всё у этих мерикосов через жопу. По мне легче запомнить, что & — это И, чем учить эти выпуклости и вогнутости.
И реализовать его как-то так:
(А вообще, как обычно создатели интерпретаторов в этом случае поступают? Шитый код, switch или ещё что?)
В бате переход возможен только на фиксированную метку.
Я писал о том, что GOTO %Variable% в батнике работать не будет. Только GOTO 1, только хардкор.
Осталось придумать, чем заменить массивы.
Случайно наткнулся, теперь вот, хотя бы знаю, как называется.
Мне вот интересно, создатели интерпретаторов в этом случае сразу переходят на генерацию кода, пишут на ассемблере, или вызов функции не такой медленный по сравнению с тем, что в этой функции будет.
{
static void * lbs[] = {&&POS,&&NEG};
goto *lbs[((unsigned int)value) >> 31];
NEG:
return (~value)+1;
POS:
return value;
}
говновычисление говномодуля
Нужен. Иначе будет неопределенное стандартом поведение. Обычно - знаковое расширение, из-за которого будет вынут -1й элемент массива вместо первого ;)
P.S. А, понял. unsigned int не нужен если value изначально беззнаковое ;)
В младшем то единицу, да. Но в остальных то тоже вылезет единица (т.к. число отрицательное и знаковый бит равен единице). А 0xFFFFFFFF это -1.
> УБ получается при сдвиге на >31 бит
А это другой уб уже. Здесь я имел в виду уб (или implementation defined, не помню уже), связанный со сдвигом отрицательного числа вправо.
Выдалось при сборке вот этого кода с оптимизацией: P.S. На -O0 это даже работает...
https://ideone.com/9FH225
А еще тут вместо магической тройки возникла магическая шестерка ;)
Я старался! А ведь мог тупо написать разность между метками, тогда бы и магическая константа не понадобилась.
Одна из самых любимых, наряду с Конкретной математикой Кнута.