LINUX.ORG.RU

[C] Порядок проверки условий

 


0

0

Неоднократно читал в разных источниках, что согласно какого то популярного стандарта C (ANSI C или C99), условия в скобках проверяются согласно последовательности их написания.

Правильно ли я понимаю, что если компилятору указали работать в режиме ANSI C и C99, то в следующей конструкции:
while (x = getx() && x > 5)
второе условие x > 5 будет проверяться всегда после выполнения getx() и никогда, ни при какой простой оптимизации, порядок проверки этих условий не поменяется?

Где "компилятору указали работать в режиме ANSI C и C99" и "ни при какой оптимизации" означает для gcc опции "-O4 -pipe -march=somearch -fomit-frame-pointer -std=c99".

Мне очень важна кроссплатформенность, но ведь основные платформы сборки моей программы, такие как последние версии Linux, FreeBSD, HP-UX, Solaris и Cygwin имеют возможность сборки согласно C99 и по-умолчанию подразумевают код ANSI C.

★★★★★

>согласно какого то популярного стандарта C

melkor217 ★★★★★
()

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

snizovtsev ★★★★★
()

// Если в стандарте сказано слева направо -- значит так и будет
// кстати, можно так ;)
while((x=getx())>5)

melkor217 ★★★★★
()
Ответ на: комментарий от saper

Естественно getargs тут меняет значение arg1 и arg2.

saper ★★★★★
() автор топика

Порядок проверки не поменяется, можешь быть уверен.

Вот стандарт ANSI C 1998-го года:

http://flash-gordon.me.uk/ansi.c.txt

Unlike the bitwise binary & operator, the && operator guarantees
left-to-right evaluation; there is a sequence point after the
evaluation of the first operand.  If the first operand compares equal
to 0, the second operand is not evaluated.

В C99 и C++ правила такие же.

ringill
()
Ответ на: комментарий от ringill

> Вот стандарт ANSI C 1998-го года:

То есть 1988-го, но это неважно в контексте обсуждаемого вопроса.

ringill
()
Ответ на: комментарий от saper

Порядок выполнения для ?:, && и || задан и гарантируется.

> while (((x = getargs(&arg1, &arg2)) < 0) && arg2 > 5)

А теперь перепишите это в несколько строк. И, возможно, тот кто будет работать после вас не будет вас ненавидеть.

dccp
()

Логические выражения в С и С++ (и почти во всех нормальных языках) вычисляются лениво. Я думал это все давно знают.

imp ★★
()
Ответ на: комментарий от guest-3484-2009

> на си так писать нельзя

почему? && это sequence point:)

dilmah ★★★★★
()
Ответ на: комментарий от guest-3484-2009

>на си так писать нельзя

K&R так писали, а нам нельзя?

imp ★★
()
Ответ на: комментарий от zh

А если getargs выдаст значение "ошибки"?
Си это не Хаскель.
>K&R так писали, а нам нельзя?

Да. А теперь мы на каждом углу слышим, что функции стандартной библиотеки "небезопасны".

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

> на си так писать нельзя

А как можно?

zzf
()
Ответ на: комментарий от guest-3484-2009

> А если getargs выдаст значение "ошибки"?

и что?

только что проверил (правда, С++):

int* p = NULL;
if( *p )  // segfault
    ...


int* p = NULL;
if( false && *p ) // ok
    ...


даже в такой извращённой форме всё безопасно.
спрашивай вопросы.

zh
()
Ответ на: комментарий от guest-3484-2009

> А если getargs выдаст значение "ошибки"? Си это не Хаскель.

Угумс. С -- это не Хаскель. Ленивость вычислений для _любой_ операции не обеспечивается. А вот для &&, ||, ?: -- гарантируется.

Т.е. второй аргумент && будет вычислен тогда и только тогда, когда первый -- истина, второй аргумент || -- когда первый ложь, второй аргумент ?: -- когда первый истина, а третий -- когда первый ложь.

kemm
()

Более того, стандарт гарантирует работоспособность кода вида

if (arg && strlen(arg)) {...

Поскольку логические выражения вычисляются слева направо и вычисление логического and (&&) прекращается сразу после того как левый операнд оказался false. Поэтому по стандарту вызова strlen под нулевой указатель в таком коде не происходит.

В логическом or правый операнд не вычисляется если левый операнд - true.

Absurd ★★★
()
Ответ на: комментарий от kemm

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

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

> программировать в стиле композиций функций - крайне вредно.

Сфигали?

> Си это ассемблер, маскирующийся под язык высокого уровня. Проблема в том, что многие этого не понимают.

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

> Если конкретнее - в хорошем коде на Си уровень вложенности должен быть равен единице, самый максимум - двум.

Это в том смысле, что есть функция main(), и всё делаем в ней? Отсыпь, а?

kemm
()
Ответ на: комментарий от guest-3484-2009

Не проецируй.

По делу-то сказать есть что, или на уроки опаздываешь?

kemm
()
Ответ на: комментарий от guest-3484-2009

>Если конкретнее - в хорошем коде на Си уровень вложенности должен быть равен единице, самый максимум - двум.

Дурак?

Absurd ★★★
()
Ответ на: комментарий от Absurd

Видел много писанины дураков.

Мне почему-то показалось, что уж тут то понимают, какой стиль надо использовать при писании на этом недоязычке. Ошибся, жаль.

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

>Мне почему-то показалось, что уж тут то понимают, какой стиль надо использовать при писании на этом недоязычке.

Какую вложенность ты имеешь в виду? Функций чтоли (вывел из твоего неприятие "композиции функций")? Функция должна делать одно дело и делать его хорошо, это единственное требование к функциям. Блоков? Тут да, возможно.

Absurd ★★★
()
Ответ на: комментарий от guest-3484-2009

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

kemm
()
Ответ на: комментарий от beastie

А не пора ли тебе в психиатрическую лечебницу? Всюду тролли видятся, нехорошо.

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

> В аргументы функций в сишке нельзя передавать другие функции т.е. a(b(), c()) - недопустимо

У-тю-тю, толстенький. На печеньку:

1) это не передача функции в качестве агрумента, о Великий Гуру.

2) и даже если действительно передавать функции (точнее, указатели на функции) в аргументах -- нельзя, потому что Великий Гуру запретил?

Ве-е-е-ели-и-и-икий знаток языка С, сразу видно...

kemm
()
Ответ на: комментарий от kemm

a(b(), c()) кстати действительно лучше не передавать, особенно если результат b и c зависит о тпорядка их выполнения

chicane
()
Ответ на: комментарий от kemm

нет.

rationale: аргументы могут передаваться в стеке, и тогда сишный способ передачи аргументов -- запихивать их в стек с конца, ну значит и вычислять удобнее с конца.

dilmah ★★★★★
()
Ответ на: комментарий от chicane

Уже разобрались. В любом случае, использование функций, зависящих от порядка их вызова, в любом виде (а не только в вызове другой функции) -- это просто ещё один способ прострелить себе ногу (ну, кроме очевидных случаев типа init_something()/do_something()).

kemm
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.