Ох уж этот синтаксис!

Votmax
Offline
Зарегистрирован: 18.06.2016

Всем привет!

Подскажите, пожалуйста, полиглоты языка Си, как трактовать такую запись:

if (!(++i%16))
{
}

Что прописано в условии? Такую запись встретил к удивлению впервые. Гуглинг как то результатов не дал.

Если кто знает ресурсы по синтаксису такого рода, напишите, пожалуйста, ссылочку.

Заранее спасибо!

sadman41
Offline
Зарегистрирован: 19.10.2016
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

увеличить i на единицу (++), потом взять остаток от деления i на 16 (%16), и если результат не равен 0 (!)  то выполнить апираторы в фигурных скопках.  По русски: 

i++;
if ( (i & 0x0F) != 0) {
 do_smth();
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

вызвать немогут. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

увеличить i на единицу (++), потом взять остаток от деления i на 16 (%16), и если результат не равен 0 (!)  то выполнить апираторы в фигурных скопках.  По русски: 

i++;
if ( (i & 0x0F) != 0) {
 do_smth();
}

всю интригу кода упорол )))

Votmax
Offline
Зарегистрирован: 18.06.2016

Большое спасибо!

Green
Offline
Зарегистрирован: 01.10.2015

Только if ((i & 0x0F) == 0), а то мужик сейчас призадумается.)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Green пишет:

Только if ((i & 0x0F) == 0), а то мужик сейчас призадумается.)

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

Green
Offline
Зарегистрирован: 01.10.2015

Это что. Давеча запускаю, до этого места доходит и зависает...
сhar data[4];
for (uint8_t i = 0; sizeof(data); i++)
  data = ' ';
3 раза всё просмотрел, пока увидел.)
 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Green пишет:

Это что. Давеча запускаю, до этого места доходит и зависает...
сhar data[4];
for (uint8_t i = 0; sizeof(data); i++)
  data = ' ';
3 раза всё просмотрел, пока увидел.)
 

ну это да, сам со второго прочтения осознал глубину, так сказать. )) А вообще первая запись топикстартера понятная, я такими только никогда не пользовался, наверное потому что так глубоко синтаксис не изучал. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

BOOM пишет:
ну это да, сам со второго прочтения осознал глубину, так сказать. )) А вообще первая запись топикстартера понятная, я такими только никогда не пользовался, наверное потому что так глубоко синтаксис не изучал.
Когда Си создавался, память стремились экономить буквально до байта. Вот и осталась в Си такая компактная запись. А потом народ разленился и на изучение языка, а так же синтаксиса забил.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

qwone пишет:

BOOM пишет:
ну это да, сам со второго прочтения осознал глубину, так сказать. )) А вообще первая запись топикстартера понятная, я такими только никогда не пользовался, наверное потому что так глубоко синтаксис не изучал.
Когда Си создавался, память стремились экономить буквально до байта. Вот и осталась в Си такая компактная запись. А потом народ разленился и на изучение языка, а так же синтаксиса забил.

я прошу прощения, не сильно в Си спец. Но разве запись высокого уровня так сильно влияет на машинный код? Я что то думал что записи вида - «i = i + 1;» и «i++;» для машинного кода эквивалентны и только для программиста это упрощение написания. Если это не так - ох уж я лузер-лузер...((

sadman41
Offline
Зарегистрирован: 19.10.2016

BOOM пишет:

я прошу прощения, не сильно в Си спец. Но разве запись высокого уровня так сильно влияет на машинный код?

Разве Вы не слышали, что в своём младенчестве Си-программы писались от руки на первобытных перфокартах? Знаете, какие они маленькие, дорогие и подотчётные? А ведь на такой бумажке требовалось компактно изложить всю поэзию алгоритма.

Поэтому никакого брахиколона не было дозволено использовать, обходились исключительно постфиксными и префиксными инкрементами и экономили на пробелах.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Green пишет:

Это что. Давеча запускаю, до этого места доходит и зависает...
сhar data[4];
for (uint8_t i = 0; sizeof(data); i++)
  data = ' ';
3 раза всё просмотрел, пока увидел.)
 

Почему же зависает, когда на самом деле зацикливается?

Эквивалент:

сhar data[4];
for (; true;)
  data = ' ';

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Ну if (!(++i%16)) считывается влет для человека активноиспользующего С хотя бы год.  А вот чтобы  расшифровать декларацию функции вроде

int (*(*fp)(int (*)(int, int), int))(int, int)

уже приходиться напрягаться

Green
Offline
Зарегистрирован: 01.10.2015
Юмор от K&R:
"Мы остановились, добившись успешной компиляции следующего:
 
for(;P("\n"),R-;P("|"))for(e=C;e-;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);
 
Мы не могли даже представить, что современные программисты будут пытаться использовать язык, допускающий подобный оператор! Мы даже собирались продать все это Советам, чтобы отбросить развитие их компьютерного дела на 20 лет назад." 
Green
Offline
Зарегистрирован: 01.10.2015

andriano пишет:

Почему же зависает, когда на самом деле зацикливается?

Затирает всю память к едреней фени). Ошибся при повторении, там было  data[i] = ' ';

 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

То ли дело брейнфак - там синтаксических ошибок практически нет. Чего написал, то и выполняется.

astwo
Offline
Зарегистрирован: 10.07.2019

Так и в Си такое же. Туфту написал туфта и выполняется.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ни фига! Просто постучите по случайным клавишам - какова вероятность, что что-то выполнится? Почти нулевая. Ругнётся компилятор и все дела. А там почти единичная.

astwo
Offline
Зарегистрирован: 10.07.2019

Так отключите контроль ошибок и вперёд. Брейнфак это как гоночная машина без тормозов - вещь для самоубийц.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

astwo пишет:
Так отключите контроль ошибок и вперёд.
Не понял что Вы имеете в виду.

Что именно и как нужно отключить, чтобы С++ компилятор скомпилировал в исполняемую программу, например, вот  такой текст: .юбяьтивс8739шощцвзуя+++-%;!

astwo
Offline
Зарегистрирован: 10.07.2019

Тупо хакнуть всю среду,что бы среда считала что никаких ошибок быть не может.

Домосед
Домосед аватар
Offline
Зарегистрирован: 18.09.2019

 

asam пишет:
int (*(*fp)(int (*)(int, int), int))(int, int)
уже приходиться напрягаться

Напрягся .. распрягся - не помогло..
Компилятор скушал сие не задумываясь :O Пронумеровал скобки..
int (*(*fp)(int (*)(int, int), int))(int, int)
    1  2   23    4  45        5     316        6
Мозг застопорился на "Указателе на функцию возвращаюшую указатель на int с двумя int аргументами.." ибо остальное в понимание невпихуемо.

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

 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

astwo пишет:
Тупо хакнуть всю среду,что бы среда считала что никаких ошибок быть не может.
Можете сказать как именно это сделать? Заткнуть так, что она так посчитала и скомпилировала данный код в нечто исполняемое? Или не можете, и просто рогом упираетесь?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
int a;//угу понятно
int *a;//ну это просто
int **a;// сложнее но понятно
int &a;// так тоже пойде
int &&a;// а вот это прошло как исключение в правилах синтаксиса

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Домосед пишет:

asam пишет:
int (*(*fp)(int (*)(int, int), int))(int, int)

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

Ок начнем со случая попроще

int (*fp)(int (*)(int, int), int)

Указатель на функцию возвращающую int у которой первый аргумент указатель на функцию возвращающую int c двумя int аргументами, а второй аргумент int.

int (*(*fp)(int (*)(int, int), int))(int, int) 

это то же самое что и предыдущая декларация, только теперь у нас указатель не на функция возвращающую int, а указатель на функцию  возвращающую указатель на функцию с двумя int аргументами возвращающая int

Как то так, если ничего не напутал.

 

Домосед
Домосед аватар
Offline
Зарегистрирован: 18.09.2019

asam пишет:

Ок начнем со случая попроще

int (*fp)(int (*)(int, int), int)

Указатель на функцию возвращающую int у которой первый аргумент указатель на функцию возвращающую int c двумя int аргументами, а второй аргумент int.

int (*(*fp)(int (*)(int, int), int))(int, int) 

это то же самое что и предыдущая декларация, только теперь у нас указатель не на функция возвращающую int, а указатель на функцию  возвращающую указатель на функцию с двумя int аргументами возвращающая int
Как то так, если ничего не напутал.

int (*(*fp)(int (*)(int, int), int))(int, int) 

указатель на функцию, у которой первый аргумент указатель на функцию возвращающую int c двумя int аргументами и второй аргумент int, возвращающую указатель на функцию с двумя int аргументами возвращающая int. Да, разжевали, стало понятно. Хитро..

Я пока для себя открыл условный оператор ?

display.drawFastHLine(8, 63, actStr != 7 ? (fEdit ? 91 : 54) : 91, (actStr==7 || actStr==3)?1:0);

Тривиально.. но какая экономия букв!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

используйте декомпозицию, парни.  меня вот DIYMan научил. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Он плохому не научит!

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Так, ну, вроде, уже почти пятница ....

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

Green пишет:

for(;P("\n"),R-;P("|"))for(e=C;e-;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);

Это разве головоломка? Тьфу!

Вот смотрите, какой скетч я нарыл на соседнем форуме! Слабо глянуть и сказать чего он такого делает? 

#define dr(n,X) (n,X)
#define cat(a, ...) primitive_cat(a, __VA_ARGS__)
#define primitive_cat(a, ...) a ## __VA_ARGS__
#define iif(c) primitive_cat(iif_, c)
#define iif_0(t, ...) __VA_ARGS__
#define    p6(n) (n+6)
#define iif_1(t, ...) t
#define check_n(x, n, ...) n
#define check(...) check_n(__VA_ARGS__, 0,)
#define probe(x) x, 1,
#define empty()
#define defer(id) id empty()
#define obstruct(...) __VA_ARGS__ defer(empty)()
#define expand(...) __VA_ARGS__
#define dec1(x) primitive_cat(dec1_, x)
#define    m6(_) (p6(_),_>=0)
#define dec1_0 0
#define dec1_1 0
#define dec1_2 1
#define dec1_3 2
#define dec1_4 3
#define dec1_5 4
#define dec1_6 5
#define dec1_7 6
#define dec1_8 7
#define dec1_9 8
#define _not_(x) check(primitive_cat(not_, x))
#define not_0 probe(~)
#define M(i, _) pinMode m6(i);
#define _compl(b) primitive_cat(_compl_, b)
#define _compl_0 1
#define _compl_1 0
#define _bool_(x) _compl(_not_(x))
#define _if_(c) iif(_bool_(c))
#define eat(...)
#define expand(...) __VA_ARGS__
#define when(c) _if_(c)(expand, eat)
#define eval(...)  eval1(eval1(eval1(__VA_ARGS__)))
#define eval1(...) eval2(eval2(eval2(__VA_ARGS__)))
#define eval2(...) eval3(eval3(eval3(__VA_ARGS__)))
#define eval3(...) eval4(eval4(eval4(__VA_ARGS__)))
#define eval4(...) eval5(eval5(eval5(__VA_ARGS__)))
#define    m20(_) ((_+1)*(20-_))
#define eval5(...) __VA_ARGS__
#define drr(n) dr(n,!digitalRead(n))
#define repeat(count, macro, ...) when(count) (obstruct(repeat_indirect) () (dec1(count), macro, __VA_ARGS__) obstruct(macro) (dec1(count), __VA_ARGS__))
#define S(i, _) digitalWrite drr(p6(i));delay m20(i);digitalWrite drr(p6(i));
#define repeat_indirect() repeat
void setup(void) { eval(repeat(8, M, ~)) }
void loop(void) { eval(repeat(8, S, ~)) }

То, что он делает вполне разумную вещь, зуб даю - проверял лично!

sadman41
Offline
Зарегистрирован: 19.10.2016

Обычно запутывают что-то очень простое. Блинк?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Блинк можно было и покороче написать. Столь же понятно, но покороче :)

MaksVV
Offline
Зарегистрирован: 06.08.2015

дак раз пинмод и диджиталврайт есть, тогда сто очей блинк

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Обычно запутывают 

Вы недооценили этот пример. Там суть вовсе не в запутывании (его-то и нет по сути), а в том, чтобы заставить препроцессор делать несвойственные ему вещи, которых он "с листа" не делает.

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

sadman41 пишет:

Обычно запутывают 

Вы недооценили этот пример. Там суть вовсе не в запутывании (его-то и нет по сути), а в том, чтобы заставить препроцессор делать несвойственные ему вещи, которых он "с листа" не делает.

Ну... Я не рассматриваю программный код как блюдо в ресторане. Скорее, применяю чисто по утилитарной необходимости - как банку тушёнки в походе. Посему - оценить, действительно, не в силах.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Так! По коду вижу - пятница )))

void setup(void) {
	pinMode ((0 +6),0>=0); 
	pinMode ((1 +6),1>=0); 
	pinMode ((2 +6),2>=0); 
	pinMode ((3 +6),3>=0); 
	pinMode ((4 +6),4>=0); 
	pinMode ((5 +6),5>=0); 
	pinMode ((6 +6),6>=0); 
	pinMode ((7 +6),7>=0); }
	
void loop(void) { 
digitalWrite ((0 +6),!digitalRead((0 +6)));
delay ((0 +1)*(20-0));
digitalWrite ((0 +6),!digitalRead((0 +6))); 
digitalWrite ((1 +6),!digitalRead((1 +6)));
delay ((1 +1)*(20-1));
digitalWrite ((1 +6),!digitalRead((1 +6))); 
digitalWrite ((2 +6),!digitalRead((2 +6)));
delay ((2 +1)*(20-2));
digitalWrite ((2 +6),!digitalRead((2 +6))); 
digitalWrite ((3 +6),!digitalRead((3 +6)));
delay ((3 +1)*(20-3));
digitalWrite ((3 +6),!digitalRead((3 +6))); 
digitalWrite ((4 +6),!digitalRead((4 +6)));
delay ((4 +1)*(20-4));
digitalWrite ((4 +6),!digitalRead((4 +6))); 
digitalWrite ((5 +6),!digitalRead((5 +6)));
delay ((5 +1)*(20-5));
digitalWrite ((5 +6),!digitalRead((5 +6))); 
digitalWrite ((6 +6),!digitalRead((6 +6)));
delay ((6 +1)*(20-6));
digitalWrite ((6 +6),!digitalRead((6 +6))); 
digitalWrite ((7 +6),!digitalRead((7 +6)));
delay ((7 +1)*(20-7));
digitalWrite ((7 +6),!digitalRead((7 +6))); }

 

Green
Offline
Зарегистрирован: 01.10.2015

ЕвгенийП пишет:

Вы недооценили этот пример. Там суть вовсе не в запутывании (его-то и нет по сути), а в том, чтобы заставить препроцессор делать несвойственные ему вещи, которых он "с листа" не делает.


Тут люди с двумя уровнями вложенности (digitalPins.h) не хотят разбираться, а вы хотите с такой головоломкой.)
В этом примере чуток бы комментариев, ну или названия более осмысленные, и всё было бы значительно приятнее.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Green пишет:

В этом примере чуток бы комментариев

Я его тут не выкладывал (было такое желание, но посчитал, что на приличном форуме такому извращению не место). Вот кто его притащил сюда с амперки (или ещё с какой какой помойки, куда он успел метастазы дать), то пусть и комментирует :)))

Вообще же, в примере демонстрируется черезжопная техника организации циклов в С-шном препроцессоре. Там ведь нет ни циклов, ни рекурсии, но "через Альпы", как видите, можно.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:

Вообще же, в примере демонстрируется черезжопная техника организации циклов в С-шном препроцессоре. Там ведь нет ни циклов, ни рекурсии, но "через Альпы", как видите, можно.

Ну это ты зря, известное изящество в этом есть! ;))))) Хотя автор явно не стремился к сокращению.

А рекурсия есть в самом процессе раскрытия макросов. В определении процесса. После подстановки новая строка просматривается на наличие в ней макросов. Вот это все и эксплуатируют, в меру начитанности. Выглядит - весьма монструозно! Если это прочитать вслух - можно вызвать некрупного демона!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:
Хотя автор явно не стремился к сокращению
К сокращению я не стремился, но и к раздутию тоже. Это почти минимальный код, если делать универсально а не под один конкретный случай.

wdrakula пишет:

А рекурсия есть в самом процессе раскрытия макросов. В определении процесса. После подстановки новая строка просматривается на наличие в ней макросов. 

Если бы задача решалась так просто, армянское радио ею бы не занималось :)

Будучи единожды развёрнут, макрос уже помечен и второй раз не разворачивается. Так что рекурсии-то как раз и нету. Например, вот такая штука 

#define FACT(n) (n < 2 ? 1 : n * FACT(n-1))

void setup(void) { Serial.print(FACT(3)); }
void loop(void) {}

не прокатит с сообщением "'FACT' was not declared in this scope"

Причём не объявлен он именно при втором проходе. Стоит убрать рекурсивный вызов - всё окажется объявленным.

Кстати, вот полный эквивалент того, что в том коде делается:

void setup(void) {
	pinMode (6, OUTPUT);
	pinMode (7, OUTPUT);
	pinMode (8, OUTPUT);
	pinMode (9, OUTPUT);
	pinMode (10, OUTPUT);
	pinMode (11, OUTPUT);
	pinMode (12, OUTPUT);
	pinMode (13, OUTPUT);
}

void loop(void) {
	digitalWrite (6, !digitalRead(6));
	delay (20);
	digitalWrite (6, !digitalRead(6));
	digitalWrite (7, !digitalRead(7));
	delay (38);
	digitalWrite (7, !digitalRead(7));
	digitalWrite (8, !digitalRead(8));
	delay (54);
	digitalWrite (8, !digitalRead(8));
	digitalWrite (9, !digitalRead(9));
	delay (68);
	digitalWrite (9, !digitalRead(9));
	digitalWrite (10, !digitalRead(10));
	delay (80);
	digitalWrite (10, !digitalRead(10));
	digitalWrite (11, !digitalRead(11));
	delay (90);
	digitalWrite (11, !digitalRead(11));
	digitalWrite (12, !digitalRead(12));
	delay (98);
	digitalWrite (12, !digitalRead(12));
	digitalWrite (13, !digitalRead(13));
	delay (104);
	digitalWrite (13, !digitalRead(13));
}

Как видите, не совсем блинк, скорее бегущий огонёк из 8-ми светодиодов с индивидуальным для каждого диода временем свечения.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Спасибо, я "в уме" развернул. Не раскрывается дважды только одноименный макрос, иначе все совсем плохо было бы.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:

Не раскрывается дважды только одноименный макрос

Таки да. Он сцуко "помечен". Причём навсегда, т.е. косвенная рекурсия через посредника тоже не прокатит :(

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

у меня чуток иной код получился

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

И чем же он иной?

MaksVV
Offline
Зарегистрирован: 06.08.2015

блин вот вы ругаетесь то а)) макросы, рекурсии.... я вижу только закорючки, а вы... прям как в фильме матрица, чес слово

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Как всегда, пришёл поручик Ржевский :(

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А я тоже о Матрице подумал))) Сидит такой оператор и видит как бабу ебут в шестером. А на самом деле код препроцессора обкатывается на эмуляторе ардуино ))))

MaksVV
Offline
Зарегистрирован: 06.08.2015

Ворота пишет:

Как всегда, пришёл поручик Ржевский :(

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

а поручик видимо boom 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

И чем же он иной?

видимо синтаксисом )))