avva: (Default)
[personal profile] avva
Гуляя по исходникам ядра Линукса в поисках информации о том, как в нём устроены 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;

Date: 2003-09-30 01:08 am (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
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 должно делать то же самое?

Date: 2003-09-30 01:10 am (UTC)
From: [identity profile] oblomov-jerusal.livejournal.com
В смысле, x || y

Date: 2003-09-30 01:11 am (UTC)
From: [identity profile] pishi-chitai.livejournal.com
MSVC такого точно не позволяет.

Date: 2003-09-30 01:18 am (UTC)
From: [identity profile] anton.livejournal.com
Это собственные расширения gcc. В стандарте ничего такого не сказано, и в msvc последнем это не работает.

Re: программистское: C, Unix

Date: 2003-09-30 01:19 am (UTC)
From: [identity profile] avva.livejournal.com
Да, спасибо. Как раз gcc.info у меня под руками не оказалось почему-то.
Если не ошибаюсь, значение 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:21 am (UTC)
From: [identity profile] avva.livejournal.com
Не очень я тогда понимаю, зачем авторам ядра Линукса с этим баловаться — не то чтобы это так уж незаменимо было...

Впрочем, может, это у меня BSDшные привычки сказываются, там стараются локализовать как можно более тщательно gcc-specific code.

Re: программистское: C, Unix

Date: 2003-09-30 01:28 am (UTC)
From: [identity profile] muchacho.livejournal.com
Из MSDN/C Language Reference:
"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."

Re: программистское: C, Unix

Date: 2003-09-30 02:00 am (UTC)
From: [identity profile] bobuk.livejournal.com
Все проще - у gcc < 3.x.x в операторе 'x?a:b' еще небыло "интеллектуальной" оптимизации кода, а операция 'x?:b' оптимизировалась.

Re: программистское: C, Unix

Date: 2003-09-30 02:01 am (UTC)
From: [identity profile] homa.livejournal.com
Хуже того, выражение A ? A : B, по-видимому, не обязательно эквивалентно выражению A ? : B.
Например, (i++) ? (i++) : i и (i++) ? : i.

Re: программистское: C, Unix

Date: 2003-09-30 02:07 am (UTC)
From: [identity profile] homa.livejournal.com
Я всегда не доверял "интеллектуальной оптимизации" (почти Ц) :)

Re: программистское: C, Unix

Date: 2003-09-30 02:13 am (UTC)
From: [identity profile] avva.livejournal.com
Да, это ясно ;)
Короче, только приключения на свою голову придумывают.

Re: программистское: C, Unix

Date: 2003-09-30 03:05 am (UTC)
From: [identity profile] bolk.livejournal.com
Вообще говоря, я мягким место чувствую, что вот так на "A ? A : B" суперпозицию нельзя навешивать.

Re: программистское: C, Unix

Date: 2003-09-30 05:35 am (UTC)
From: [identity profile] arbat.livejournal.com

Замечательно. A теперь скажите, какой результат будет у

int i = 1;
int j = i++ ? i++ : i;


Re: программистское: C, Unix

Date: 2003-09-30 05:47 am (UTC)
From: [identity profile] homa.livejournal.com
В вашем случае результат будет таким: i = 3, j = 2.

В случае же
int i = 1;
int j = i++ ? : i;

результат будет несколько иным: i = 2, j = 2.

Т.е., во втором случае пропущенное выражение вновь вычисляться не будет -- во всяком случае, надеюсь на это. Иначе это уже не С, а, простите, Васик какой-то.

Re: программистское: C, Unix

Date: 2003-09-30 06:05 am (UTC)
From: [identity profile] homa.livejournal.com
Даже, наверно, i = 2, j = 1. Проверить не на чем.

Re: программистское: C, Unix

Date: 2003-09-30 09:15 am (UTC)
From: [identity profile] dvv.livejournal.com
Никакого - это не является программой на C :-)

А так - j будет равно 2, i будет равно 3. Стандарта C под рукой нет, а в C++ в 5.16/1 явно сказано, что все side effects of the first expression [...] happen before the second or third expression is evaluated.

Date: 2003-09-30 10:26 am (UTC)
From: [identity profile] vzaliva.livejournal.com
я посмотрел по стандарту C99 - такое запрещено.

Date: 2003-09-30 10:41 am (UTC)
From: [identity profile] avva.livejournal.com
Спасибо!

Re: программистское: C, Unix

Date: 2003-09-30 12:10 pm (UTC)
From: [identity profile] arbat.livejournal.com

Отлично :-) Однако, Вам потребовалось заглянуть в стандарт, чтобы проверить порядок выполнения операторов. При этом Вы повели себя как интеллигентный человек, который знает, что порядок вообще говоря может быть всякий, что иногда он задан стандартом, а иногда нет, и который знает, куда посмотреть и держит хоть один из стандартов "под руками". Поздравляю, Вы входите в 1% людей, которые так себя ведут.

Беда в том, что Ваш код потом будет изучаться и, возможно, "улучшаться" другими, которые с вероятностью 99% не войдут в Ваш интеллигентский 1% :-)
Мораль - так писать не надо, и сокращенной версией пользоваться - тоже. Экономия копеечная, а потом кто-то в темном лесу напорется на сук.

Re: программистское: C, Unix

Date: 2003-09-30 12:12 pm (UTC)
From: [identity profile] arbat.livejournal.com

Так, наверное или точно? И как узнать?
"Проверить" - это не разговор.

Re: программистское: C, Unix

Date: 2003-09-30 12:21 pm (UTC)
From: [identity profile] dvv.livejournal.com
Хм? Мне потребовалось заглянуть в стандарт чтобы привести цитату, chapter и verse, что никак не говорит о моём немедленном знании или незнании сути данного конкретного вопроса. Что же касается моего стиля кодирования, так я стараюсь, чтобы он был максимально прозрачным и однозначным даже для кодеров с весьма общим представлением о языке, чтобы у любителей гадать о моих намерениях было как можно меньше материала для их любимого занятия.

Re: программистское: C, Unix

Date: 2003-09-30 12:24 pm (UTC)
From: [identity profile] dvv.livejournal.com
В догонку:

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

Re: программистское: C, Unix

Date: 2003-09-30 12:27 pm (UTC)
From: [identity profile] arbat.livejournal.com
Вы хотите сказать, что были абсолютно, на 100% - уверены, что нету никаких проблем? :-)



Re: программистское: C, Unix

Date: 2003-09-30 12:31 pm (UTC)
From: [identity profile] dvv.livejournal.com
Я хочу сказать, что я абсолютно, на 100% был уверен, что с точки зрения языка никаких проблем в примере не было.

Re: программистское: C, Unix

Date: 2003-10-01 12:21 am (UTC)
From: [identity profile] homa.livejournal.com
А вы, прошу пардону, спорите с моей первоначальной репликой? Или просто решили мне экзамен устроить? :) Придумать произвольную ситуацию, потребовать ее "в уме" проиграть, а потом еще и настаивать на точности? Как говаривал кто-то из физиков, "мой книжный шкаф знает больше меня, но физик не он, а я".

Date: 2003-10-01 06:09 am (UTC)
From: [identity profile] ex-innin997.livejournal.com
это логично, ведь condition ? expression : expression это условный оператор, возвращающий какое-либо значение. В Perl тоже работает
print 1 + (1 ? 1 : 3);

Date: 2003-10-01 06:15 am (UTC)
From: [identity profile] ex-innin997.livejournal.com
прошу прощения, мой комментарий совсем не по теме вашего рассуждения. Просто я читал это обсуждение пару дней назад, и был увлечён собственными мыслями.
В Perl без одного операнда $a = ($b ? : $d); не работает

Re: программистское: C, Unix

Date: 2003-10-01 04:46 pm (UTC)
From: [identity profile] arbat.livejournal.com
Нет, не беспокойтесь, я Вас экзаменовать не собирался.
Можете посмотреть обсуждение в паралелльном треде.
Суть в том, что конструкция, в которой возможны сомнения, а необходимости нету никакой - не должна употребляться вообще.

December 2025

S M T W T F S
  123 4 56
78 9 10 11 1213
1415 1617181920
21 22 23 24 2526 27
2829 30 31   

Most Popular Tags

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 1st, 2026 10:59 pm
Powered by Dreamwidth Studios