программистское: C, Unix
Sep. 30th, 2003 10:52 amГуляя по исходникам ядра Линукса в поисках информации о том, как в нём устроены real-time signals (см. 'man 7 signal', если вы не знаете, что это такое), я обнаружил случайно весьма удивительную конструкцию в C:
Оператор условного выбора ?:, но без второго операнда. То есть вместо обычного, скажем,
a = b ? c : d;
(что означает: если b, то присвоить a=c; иначе присвоить a=d), пишется, например, так:
a = b ? : d;
По контексту становится ясно, что это означает: если b, то a=b; иначе a=d.
(кстати, весьма неинтуитивно; самым очевидным кажется такая интерпретация: если b, то a не меняется, иначе a=d. Но, конечно, на самом деле такая интерпретация невозможна, т.к. согласно семантике языка выражение (b ? : d) должно иметь какое-то определённое значение)
Так вот, я такого никогда в жизни не видел, и не подозревал даже, что так можно писать. Теперь мне интересно, это разрешено каким-то стандартом, или это какое-то расширение gcc? Знает ли кто?
Пример "живого" использования в исходнике ядра Линукса см. например в файле net/ipv4/tcp.c, там их шесть штук (в 2.4.20 по крайней мере). Например:
val = (tp->keepalive_time ? : sysctl_tcp_keepalive_time)/HZ;
Оператор условного выбора ?:, но без второго операнда. То есть вместо обычного, скажем,
a = b ? c : d;
(что означает: если b, то присвоить a=c; иначе присвоить a=d), пишется, например, так:
a = b ? : d;
По контексту становится ясно, что это означает: если b, то a=b; иначе a=d.
(кстати, весьма неинтуитивно; самым очевидным кажется такая интерпретация: если b, то a не меняется, иначе a=d. Но, конечно, на самом деле такая интерпретация невозможна, т.к. согласно семантике языка выражение (b ? : d) должно иметь какое-то определённое значение)
Так вот, я такого никогда в жизни не видел, и не подозревал даже, что так можно писать. Теперь мне интересно, это разрешено каким-то стандартом, или это какое-то расширение gcc? Знает ли кто?
Пример "живого" использования в исходнике ядра Линукса см. например в файле net/ipv4/tcp.c, там их шесть штук (в 2.4.20 по крайней мере). Например:
val = (tp->keepalive_time ? : sysctl_tcp_keepalive_time)/HZ;
no subject
Date: 2003-09-30 01:08 am (UTC)File: gcc-3.3.info, Node: Conditionals, Next: Long Long, Prev: Lvalues, Up:\ C Extensions Conditionals with Omitted Operands ================================== The middle operand in a conditional expression may be omitted. Then if the first operand is nonzero, its value is the value of the conditional expression. Therefore, the expression x ? : y has the value of `x' if that is nonzero; otherwise, the value of `y'. This example is perfectly equivalent to x ? x : yВроде бы x && y должно делать то же самое?
no subject
Date: 2003-09-30 01:10 am (UTC)Re: программистское: C, Unix
Date: 2003-09-30 01:19 am (UTC)Если не ошибаюсь, значение x||y не гарантировано ==x в случае, если x не равно 0; всё, что гарантировано, это то, что only x is evaluated and the result evaluates as true (т.е. компилятор может выбрать ставить всегда 1 в качестве результата в таких случаях). Впрочем, моя память, возможно, меня подводит в этом пункте.
(а вот в перле, скажем, x||y всегда равно x, если x evaluates as true)
Re: программистское: C, Unix
Date: 2003-09-30 01:28 am (UTC)"The logical-OR operator performs an inclusive-OR operation on its operands. The result is 0 if both operands have 0 values. If either operand has a nonzero value, the result is 1."
no subject
Date: 2003-09-30 01:11 am (UTC)no subject
Date: 2003-09-30 01:18 am (UTC)Re: программистское: C, Unix
Date: 2003-09-30 01:21 am (UTC)Впрочем, может, это у меня BSDшные привычки сказываются, там стараются локализовать как можно более тщательно gcc-specific code.
Re: программистское: C, Unix
Date: 2003-09-30 02:00 am (UTC)Re: программистское: C, Unix
Date: 2003-09-30 02:07 am (UTC)Re: программистское: C, Unix
Date: 2003-09-30 02:01 am (UTC)Например, (i++) ? (i++) : i и (i++) ? : i.
Re: программистское: C, Unix
Date: 2003-09-30 02:13 am (UTC)Короче, только приключения на свою голову придумывают.
Re: программистское: C, Unix
Date: 2003-09-30 03:05 am (UTC)Re: программистское: C, Unix
Date: 2003-09-30 05:35 am (UTC)Замечательно. A теперь скажите, какой результат будет у
int i = 1;
int j = i++ ? i++ : i;
Re: программистское: C, Unix
Date: 2003-09-30 05:47 am (UTC)В случае же
int i = 1;
int j = i++ ? : i;
результат будет несколько иным: i = 2, j = 2.
Т.е., во втором случае пропущенное выражение вновь вычисляться не будет -- во всяком случае, надеюсь на это. Иначе это уже не С, а, простите, Васик какой-то.
Re: программистское: C, Unix
Date: 2003-09-30 06:05 am (UTC)Re: программистское: C, Unix
Date: 2003-09-30 12:12 pm (UTC)Так, наверное или точно? И как узнать?
"Проверить" - это не разговор.
Re: программистское: C, Unix
Date: 2003-10-01 12:21 am (UTC)Re: программистское: C, Unix
Date: 2003-10-01 04:46 pm (UTC)Можете посмотреть обсуждение в паралелльном треде.
Суть в том, что конструкция, в которой возможны сомнения, а необходимости нету никакой - не должна употребляться вообще.
Re: программистское: C, Unix
Date: 2003-09-30 09:15 am (UTC)А так - j будет равно 2, i будет равно 3. Стандарта C под рукой нет, а в C++ в 5.16/1 явно сказано, что все side effects of the first expression [...] happen before the second or third expression is evaluated.
Re: программистское: C, Unix
Date: 2003-09-30 12:10 pm (UTC)Отлично :-) Однако, Вам потребовалось заглянуть в стандарт, чтобы проверить порядок выполнения операторов. При этом Вы повели себя как интеллигентный человек, который знает, что порядок вообще говоря может быть всякий, что иногда он задан стандартом, а иногда нет, и который знает, куда посмотреть и держит хоть один из стандартов "под руками". Поздравляю, Вы входите в 1% людей, которые так себя ведут.
Беда в том, что Ваш код потом будет изучаться и, возможно, "улучшаться" другими, которые с вероятностью 99% не войдут в Ваш интеллигентский 1% :-)
Мораль - так писать не надо, и сокращенной версией пользоваться - тоже. Экономия копеечная, а потом кто-то в темном лесу напорется на сук.
Re: программистское: C, Unix
Date: 2003-09-30 12:21 pm (UTC)Re: программистское: C, Unix
Date: 2003-09-30 12:27 pm (UTC)Re: программистское: C, Unix
Date: 2003-09-30 12:31 pm (UTC)Re: программистское: C, Unix
Date: 2003-09-30 12:24 pm (UTC)более того, кодер, который при мне демонстрирует такой код в процессе выполнения своих служебных обязанностей, вполне рискует.
no subject
Date: 2003-09-30 10:26 am (UTC)no subject
Date: 2003-09-30 10:41 am (UTC)no subject
Date: 2003-10-01 06:09 am (UTC)print 1 + (1 ? 1 : 3);
no subject
Date: 2003-10-01 06:15 am (UTC)В Perl без одного операнда $a = ($b ? : $d); не работает