LINUX.ORG.RU

Порядок вычисления выражения Си

 , ,


2

3

Например, в результате вычисления операторов присваивания (см. пример) значение переменной i будет равно 9 или 11 в зависимости от того, какое подвыражение второй операции будет вычислено первым. Таким образом, с использованием разных компиляторов можно получить различные результаты.

j=3;
i=(k=j+1)+(j=5);

clang и gcc выдает i=9; у кого нибудь может быть иначе?

★★★★★
Ответ на: комментарий от batbko

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

и сколько строчек я за день напишу, если буду про каждую задумываться? Или про каждую не надо? Про какую надо?

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

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

Я даже так стараюсь не применять, а то ошибиться и присвоить не то не туда довольно легко.

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

ну говорю же: всегда можно добавить лишнюю строчку и/или переменную. И читать проще, и компилятор поймёт как надо. А на скорость это не влияет. Если строчка действительно лишняя, компилятор сам её выкинет.

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

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

Нет, не может.

я второй раз не собираюсь часами такую тупую ошибку искать, из-за того, что поверил в твоё «не может». Если тебе это нравится — верь, что «не может».

PS: прикольный аватарчик.

emulek
()

clang и gcc выдает i=9

Clang is designed to offer a complete replacement to the GNU Compiler Collection (GCC)

(c) Wikipedia

true_admin ★★★★★
()

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

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

ну говорю же: всегда можно добавить лишнюю строчку и/или переменную. И читать проще, и компилятор поймёт как надо.

+100500^2

Ой, не так, вот так:

+100500
100501^2
Хм, хотя магические числа это ещё хуже, тогда вот так:
    #include <stdio.h>

    int main(void)
    {
        long int score = 100500;
        long int buff = 0;

        score++;
        buff=(score * score);
        printf("%ld\n",buff);
        return 0;
    }

10100451001 ::)

Dron ★★★★★
()
Последнее исправление: Dron (всего исправлений: 1)
Ответ на: комментарий от Aswed

Подобные ситуации не описаны стандартом и потому в компиляторах поведение реализуется по мнению разработчика.

разработчики полагают, что в таком коде не может быть неоднозначности, и что его нужно выполнять максимально быстро. Например x-- - --x превращается в константу 0(проверял на gcc с O2). А проблемы говнокодеров, которые такое говно пишут, никого не волнует(т.е. компилятор просто не учитывает, что тут может быть побочный эффект).

А вообще подобный стиль есть говнокод жуткий и если ты применяешь его в разработке, а не только ради интереса уточняешь, то позор тебе и пусть соседи закидают тебя фекалиями.

этот код этот код эквивалентен русской фразе «полюбуйтесь, какой я феерический мудазвон!». Тут ничего кидать ИМХО не нужно. Нужно аборт делать, но уже поздно.

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

сходил по ссылке, поразило:

Duplicates: 762 816 1039 1570 2550 2673 3165 3324 4978 5051 5159 5494 5516 5724 6409 6765 6790 6891 7135 8175 9334 9675 9693 10947 11363 12552 13403 14417 14951 15012 15103 16309 16887 17018 17095 17253 17282 17507 17639 19798 20181 21246 21404 22248 24015 26060 26418 26642 26730 26820 26923 27153 27233 27344 27646 30935 31398 32067 32133 32536 33043 33248 33270 37800 38516 39143 40366 42711 (view as bug list)

а я думал, что мудаки — russian only. Нет!

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

по уму надо uint64_t

я такие вещи так считаю:

$ echo "score=100500
> score++
> score*score" | bc
100500
10100451001
emulek
()
Ответ на: комментарий от Dron

отвык от 32.

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

PS: в i686 sizeof(long int)==4.

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

А вообще, да, мне следует освежить в памяти С. Забыл всё нахрен ::)

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

для 10100451001 64 бит вполне хватит. Это <9223372036854775808

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

Просто мне следует вспомнить/выучить, мат часть. С освоением php вся система типов из боши повылетала ::)

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

constexpr

вот задолбал. Компилятор без тебя это умеет.

auto

это только в C++11, да и не для этого оно.

PRIu64

а это ещё что за ☣?

pow<2>(score + 1));

слушай, ты вообще на каком ЯП пишешь? На кой ляд так делать?

PS: вот как раз об этом я и говорил — первый признак начинающего говнокодера — нафтыкать где можно и где нельзя надёрганных из http://en.wikipedia.org/wiki/C 11#Extensions_to_the_C.2B.2B_core_language херовин. Тупо «чтоб было».

Ну молодец, продолжай.

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

Ну чего от тебя ещё услышать произнося php ::) Не ругайся, злоба штука плохая, особенно если относить её к неодушевлённым предметам.

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

Ну чего от тебя ещё услышать произнося php ::) Не ругайся, злоба штука плохая, особенно если относить её к неодушевлённым предметам.

ты не понял, если и есть злоба, то злюсь я на себя. Php отупляет. Не нужно на нём что-то серьёзное писать, ничего хорошего ИМХО не получится. Получится по любому куча говна, в которой противно ковыряться.

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

Я два варианта написал — на C++ и на C.

Компилятор без тебя это умеет.

Компилятор не умеет в автоматическую const-correctness. Если вещь предполагается константной — ставим const. Различие constexpr/const тут не принципиально, из constexpr следует const, const можно использовать в качестве constexpr, в данном случае это намёк на то что подразумевается больше «constant expression», чем «constant object».

да и не для этого оно

У нас есть 100500l, 100500ll и т.п. суффиксы, int(100500), uint64_t(100500) и т.п. конструкторы, так что я намекаю на важность использования таких суффиксов и конструкторов, чтобы неявными приведениями не получить int (стандартный тип для обычных числовых целых литералов) и не осечься — (1 << ...) будет сдвигать в int, а нам может быть нужно больше, pow<2>(100500 + 1) вызовет специализацию для int, а нам нужно pow<2>(uint64_t(100500) + 1) — для uint64_t. Дальше была тема про вынесение магической uint64_t(100500) в именованную сущность — вот auto score = uint64_t(100500);, или uint64_t score = 100500;, но наверно не uint64_t score = uint64_t(100500);.

а это ещё что за ☣?

http://en.cppreference.com/w/c/types/integer

слушай, ты вообще на каком ЯП пишешь

Этот кусок — обычный C++ (не 11).

На кой ляд так делать?

А как надо? pow(score + 1, 2), pow_2(score + 1), square(score + 1) или (score + 1) * (score + 1)?

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от quasimoto

Компилятор не умеет в автоматическую const-correctness.

вот видишь... В общем случае — не умеет. В частном, если ты не говнокодер, то умеет. Т.е. либо ты этого не знаешь, либо знаешь, но ты говнокодер.

Если вещь предполагается константной — ставим const.

а оно и так будет const, т.к. ты её не меняешь. Т.е. в коде будет просто 100500+1→100501²→10100451001. Вот если-бы ты её говнокодом привёл к int*, то да. Компилятор-бы решил «хрен тебя знает», и она стала-бы неconst.

в данном случае это намёк на то что подразумевается больше «constant expression», чем «constant object».

так пиши expression, компилятор сам посчитает. Зачем в коде лишние намёки? Тебе не пофиг, как это будет считаться и когда? А ты зачем-то пишешь ненужный для понимания кода constexpr, т.е. ненужный мусор.

а нам может быть нужно больше, pow<2>(100500 + 1) вызовет специализацию для int

вот видишь, сколько проблем из-за pow<2>?

(score + 1) * (score + 1)?

this

Или там int64_t score1 = score+1; score1*score1; раз тебе надо именно 64х битный int, и никакой иной. Компилятор всё равно выкинет ненужный score1.

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

кстате примеры в школьном учебнике математики доже дебильные и не нужные IRL. Я в курсе, у меня сын первый класс почти окончил. Потому что примеры нужны для _обучения_, а НЕ для работы.

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

а оно и так будет const, т.к. ты её не меняешь

Если ты не (собираешься) меняешь, то ты ставишь const — элементарно же.

А ты зачем-то пишешь ненужный для понимания кода constexpr, т.е. ненужный мусор.

С ним всё ок, как и с const.

вот видишь, сколько проблем из-за pow<2>?

Никаких проблем. 100500 -> int(100500) -> ... это вообще так в выражениях (вне инициализации).

this

овер-дофига-буков * эти-же-овер-дофига^W^W^W^W, та ну нафиг.

Или там int64_t score1 = score+1; score1*score1;

Я и говорю — языки с выражениями уже давно тут, а ты как в SSA/ассемблере ручками хочешь их расписывать :)

«Полезный» пример использования pow<> что-ли?

Обобщение, в контексте алгоритма для умножений/степеней в произвольных полугруппах, моноидах и группах — http://www.stepanovpapers.com/Journeys/Journeys-0.3.pdf, http://www.youtube.com/watch?v=PtGVOGui7q4&index=3&list=PLHxtyCq_WDLV... http://www.youtube.com/watch?v=etZgaSjzqlU&index=4&list=PLHxtyCq_WDLV...

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

тонко ты его вынудил заподозрить создателя (STL) в нубстве в С++.

о вэйт!

Степанов сам сознаётся , что

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

2. он не знает С++ ибо его друзья в числе которых Страуступ подогнали ему лично очищенное подмножество от С++ ( описано в Началах).

в кои то веки емулек прав то. так то.

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

ты совсем ?

он показывал на примере .

если операция ассоциативна то для неё всегда есть возможность оптимизации вместо линиии на логарифм.

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

или нахождение кратчайших путей на графе.

qulinxao ★★☆
()
Последнее исправление: qulinxao (всего исправлений: 1)
Ответ на: комментарий от quasimoto

Если ты не (собираешься) меняешь, то ты ставишь const — элементарно же.

а если собираешься? А знаешь, что самое постоянное на свете?

С ним всё ок, как и с const.

ИМХО надо это всё ставить тогда, и только тогда, когда оно нужно по смыслу. Если смысл сущности константный, то она должна быть const, если это и так не понятно. int x = 17; и так — константа(пока её не поменяли ниже по коду. const нужно только для того, что менять бессмысленно, типа π например, а вот что это за x, я не знаю) А вот что такое uint64_t(100500); я вижу и без тупых подсказок.

Никаких проблем. 100500 -> int(100500) -> ... это вообще так в выражениях (вне инициализации).

там по смыслу каста вообще не должно быть. 100500 в int влезает, а вот результат надо в int64_t.

овер-дофига-буков * эти-же-овер-дофига^W^W^W^W, та ну нафиг.

да. Конечно лучше какой-то мутный шаблон от Стенпанова, который полдня искать в stl, да? Ты его хоть видел? Я — не видел. И потому лучше овер-дофига-буков * эти-же-овер-дофига, чем «иди туда, не знаю куда, сделай то, незнаю что»

Я и говорю — языки с выражениями уже давно тут, а ты как в SSA/ассемблере ручками хочешь их расписывать :)

непонятные выражения не нужны.

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

ты белены объелся? Мне в квадрат возвести надо обычное целое число. А если надо будет в GF(1399), то твоё дерьмо всё равно не осилит, один хрен свой класс писать.

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

тонко ты его вынудил заподозрить создателя (STL) в нубстве в С++.

если честно, то я вообще не считаю STL частью C++.

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

если операция ассоциативна то для неё всегда есть возможность оптимизации вместо линиии на логарифм.

это ты совсем. Что ты там собрался оптимизировать для квадрата? И про эту оптимизацию любой дурак знает.

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

а оптимизация нужна только в _конкретном_ случае, и далеко не во всяком. Кстати, а вот зачем лично тебе нужно было «быстое точное вычисление фибоначей через умножение матриц»? Расскажешь? И сколько раз в жизни?

или умножение через сложение или возведение через логарифм умножений или ещё какая операция .

это любой школьник обязан знать. Иначе, на кой ляд он 11 лет учил математику? Что-бы тупо множить на одно и тоже Over9000 раз? Кстати2: на кой ляд тебе надо было возведение в Over9000ю степень? Причём не степенной ряд(который рекуррентный), а вот так ВНЕЗАПНО Over9000я?

или нахождение кратчайших путей на графе.

тут для каждого класса нужна своя оптимизация. А в 95% не нужна.

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

Тут да, неопределённое поведение выходит.

тут скорее «неопределённый результат». Т.е. какой-то результат ты получишь, а какой именно — хз. UB это уже покруче, типа деления на ноль, или разименования NULL. Тут вообще что угодно может случится. Или не случится. Или случится, но когда — хрен его знает.

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

это любой школьник обязан знать.

и тем не менее, неделю назад я лично написал код, который возводит число путём умножения в цикле в 1400ю степень. И даже не подумаю этот код менять. А зачем, если он работает быстрее в миллион раз как минимум, чем программа? Что-бы программа работала на 1/1000000 раз быстрее? Там, если подумать, можно и в 10 раз наоптимизировать.

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

а если собираешься?

Я не собирался. Надо менять — ну тогда не надо ставить, что мы вообще об этом говорим.

там по смыслу каста вообще не должно быть. 100500 в int влезает, а вот результат надо в int64_t.

Я хочу square (^2) в частности и pow в натуральные (целые) вообще для любых типов, если выражение будет в int, то при применении такой функции результат тоже, так что нужен каст или суффикс.

И я тут не провожу никакой параллели между Степановским примером и pow<size_t>(I x) (который ты сам напишешь в пару строк), это две несвязанных вещи (наверное, надо посмотреть что я хочу :)).

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

Надо менять — ну тогда не надо ставить, что мы вообще об этом говорим.

ну ты ещё комммент туда припиши:

uint64_t(//это целое ббез знака из 64х бит
100500// это сто тысяч и пятьсот.
);// скобки надо закрывать, иначе не соберётся, уже пытался
а то непонятно сразу.

Я хочу square (^2) в частности и pow в натуральные (целые) вообще для любых типов, если выражение будет в int, то при применении такой функции результат тоже, так что нужен каст или суффикс.

для квадрата int*int=uint64_t вероятность переполнения равна нулю, для ВСЕХ остальных показателей ≥8 вероятность переполнения 95%. Ты второй суперкиллерхакер? А, ну тогда считай. Ещё тест скорости сделай и тему открой.

И я тут не провожу никакой параллели между Степановским примером и pow<size_t>(I x) (который ты сам напишешь в пару строк)

я не пишу код для деления на ноль, суммирования 32К float'ов на SIMD, и логарифмически быстрого возведения в Over9000 степень целого числа.

Кстати, ты знаешь сколько цифр в числе 5^9001? Примерно 6291. А сколько в 10^Over9001? точно Over9000. Т.ч. считай, uint64_t для этиъх целей подходят.

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

ну ты ещё комммент туда припиши

Вот чё ты прыгаешь — мы про const, принципы расставления которого элементарны.

int*int=uint64_t

Ты не понимат — T pow(T, [Unsigned]Integer), один тип в результате и аргументе.

100500ULL

Да, про суффиксы я уже писал тут.

// Хотя кто тебе сказал, что ull это 64 бит?

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от emulek

ну да . прежде всего (после исправного кода) gprof (ежель нужно)(или какой аналог по продвинутей)

фибоначи через матрицы было вообщето-то контрпримером фибоначи через рекурсию (которой там фибоначи много) а затем её сверх низведение до линии через меморизацию 2ух текущих соседей.

реально же примерами есть классическое логарифмическое возведение и поиск кратчайших ( либо связностей если на булевых) у флойда?

а все это приводилось и здесь и там как примеры обобщённого.

qulinxao ★★☆
()
Ответ на: комментарий от emulek
template <typename T>
T pow(T a, unsigned n) {
    return generic::power_monoid<generic::integer_multiplicative_monoid<T>>(a, n);
}

uint64_t t1(uint64_t x) { return pow(x, 2); }
//	movq	%rdi, %rax
//	imulq	%rdi, %rax
//	ret

uint64_t t2() { return pow(uint64_t(100500) + 1, 2); }
//	movabsq	$10100451001, %rax
//	ret
quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Вот чё ты прыгаешь — мы про const, принципы расставления которого элементарны.

принципы действительно элементарны:

1. ставь const всегда

2. исключение: когда он уже и так неявно стоит. Например НЕ нужно писать x=(const int)123;, т.к. 123 и так const int. Вот твой пример как раз под это исключение и попадает.

Ты не понимат — T pow(T, [Unsigned]Integer), один тип в результате и аргументе.

это ты не понимаешь: в реализации таки два. И что-бы компилятор мог бы это оптимизировать, кастовать нужно _непосредственно_ в умножении. Тогда он выбросит каст, который в реализации не нужен. А если ты сделаешь например функцию, которая принимает uint64_t, то компилятор будет вынужден использовать 64х битное умножение, и потом отсекать «лишние» старшие 64 бита, в которых всегда будет 0. А всё от того, что ты свернул x*y в функцию pow(x,2). Добавил лишнюю сущность.

Хотя кто тебе сказал, что ull это 64 бит?

стандарт. Это 64 бит. Может быть и 64+64, но моя программа от этого не сломается. Пусть мои дети переписывают ☺, если тут у них будет узкое место в 2050ом году. Хотя вряд-ли тут будет узкое место и потребуется переписывать.

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