Блог пользователя freopen

Автор freopen, 13 лет назад, По-русски

... это не g++, это minGW.

MinGW (англ. Minimalist GNU for Windows), ранее mingw32, — нативный программный порт GNU Compiler Collection (GCC) под Microsoft Windows, вместе с набором свободно распространяемых библиотек импорта и заголовочных файлов для Windows API. (Википедия).

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

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

#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
using namespace std;

bool fail1=0, fail2=0;

bool lsw0(int a, int b) {
  // В исходном массиве нет нулей, 
  // компаратор не может запуститься от нулевого аргумента
  if (a==0 || b==0) if (!fail1) {fail1 = 1; cout << "Fail #1" << endl;}
  // Арктангенс от положительного числа и нуля согласно man pages
  // равен pi/2 независимо от первого аргумента
  if (atan2(a,0) < atan2(b,0)) if (!fail2) {fail2 = 1; cout << "Fail #2" << endl;}
  // Это отношение транзитивно, если арктангенс зависит только от входных данных
  return atan2(max(a,1),0) < atan2(max(b,1),0);
}

int main () {
  #ifdef __MINGW32__
  cout << "I'm running on MinGW 32" << endl;
  #endif
  vector<int> perm;
  for (int j=1;j<250;j++) {
    perm.push_back(j);
  }
  sort(perm.begin(),perm.end(),lsw0);
}

На нормальных компиляторах этот код отработает без ошибок и ничего не выведет на экран. Но не на MinGW! Фейл первый: если запустить сортировку сортировать массив (1,2,...,249), может ли компаратор запуститься от нулевых аргументов? Как правило, функцию сортировки совершенно не волнует отношение порядка для элементов вне массива. Но MinGW оказался очень любопытным компилятором и таки заглянул туда. Фейл второй: как вы думаете, что больше: угол от OX до вектора (0;1) или угол от OX до вектора (0,2). Вот MinGW искренне думает, что они вполне себе могут отличаться. Ну и наконец, пишем более-менее стандартный компаратор, который отработает верно независимо от реализации atan2, лишь бы сам atan2 не рухнул. Но и здесь нас ждет провал, сортировка падает в RE.

Вывод: если вы не желаете экстремального поиска багов компилятора во время контеста, используйте компилятор Visual C++. Также, наверное, стоит сменить название компилятора в системе с g++ на MinGW, чтобы новички не удивлялись, почему в системе код падает, а у них на локальном компьютере все работает.

UPD. SkyHawk подсказывает, что g++ может вызывать fail #1, если компаратор не является strict weak ordering. Однако, MinGW умеет так делать даже при верном компараторе.

UPD2. Делаю вывод, что все эти фейлы порождаются одной и той же ошибкой: в MinGW strict weak ordering не выполняется даже для double.

UPD3. Ссылка от DAle про причины подобных ошибок при операциях с плавающей точкой.

  • Проголосовать: нравится
  • -1
  • Проголосовать: не нравится

»
13 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится

На счет Fail #1 — в случае ошибки в компараторе программа, откомпилированная в VS или gcc, тоже может вызвать компаратор от отсутствующего значения.

»
13 лет назад, # |
  Проголосовать: нравится +6 Проголосовать: не нравится

Я считаю, что ты выбрал слишком яркий и обманчивый заголовок. Как ты сам признаешь, не GCC виноват, а MinGW.

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится -13 Проголосовать: не нравится

    Да, я имел в виду немного другой заголовок. Так лучше?

»
13 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

Я вот как раз хотел узнать на онсайте КРОКа, но потом забыл.. По каким причинам используются c одной стороны MinGW, а с другой Mono?

»
13 лет назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

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

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    А при чем тут погрешности? Во-первых, должно получиться ровно pi/2. Во-вторых, даже если не ровно, должно от запуска к запуску получаться одно и то же число, тогда получается, что мы как бы сортим числа atan2(x,0) по возрастанию. Тогда компаратор все равно корректен.

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Добавь в код

      cout << lsw0(1, 32) << lsw0(32, 1);

      и ты обнаружишь, что у тебя компаратор оба раза вернёт значение 1. Что мягко говоря не совсем то, чего ты ожидаешь увидеть.

      • »
        »
        »
        »
        13 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится -8 Проголосовать: не нравится

        Мой компилятор выдает 0 0.

        UPD. Как и компилятор ideone.

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Хм. На CF 2005я студия тоже выдаёт 0 0, правда Fail #2 всё равно вывело. У меня же 1 1. (видимо опции компиляции на CF немного другие).

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Ну стандартом я самоуверенно обозвал man pages по atan2. Он, естественно, неприменим к MS Visual C++.

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится -8 Проголосовать: не нравится

        Стоп! А у вас какой компилятор? Вам не кажется ненормальным, что atan2(1,0) < atan2(32,0), и одновременно atan2(32,0) < atan2(1,0). Кажется, я нашел fail#3 :).

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится +7 Проголосовать: не нравится

          Еще интересный факт: atan2 отличается от std::atan2. Код:

          #include <cstring>
          #include <cstdio>
          #include <cmath>
          
          const int a = 1;
          const int b = 32;
          
          int main () {
            #ifdef __MINGW32__
            printf("I'm running on MinGW 32\n");
            #endif
          
            printf("%d %d %d\n",
              atan2(a, 0) < atan2(b, 0),
              atan2(a, 0) == atan2(b, 0),
              atan2(a, 0) > atan2(b, 0));
            printf("%d %d %d\n",
              std::atan2(a, 0) < std::atan2(b, 0),
              std::atan2(a, 0) == std::atan2(b, 0),
              std::atan2(a, 0) > std::atan2(b, 0));
            return 0;
          }
          

          У меня выводит

          0 1 0
          1 0 0
          
          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            А вот это неожиданность. Казалось бы, нафига так делать? Никакой пользы, только хорошо запрятанный источник ошибок.

            • »
              »
              »
              »
              »
              »
              »
              13 лет назад, # ^ |
                Проголосовать: нравится +2 Проголосовать: не нравится

              Не знаю, но еще мораль: нефиг писать using namespace std;, а то можно-таки напороться. Ну или EPS использовать.

              • »
                »
                »
                »
                »
                »
                »
                »
                13 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                Мораль в том, что не надо пользоваться C-шными функциями, только std::...

                Хотя на олимпиадах с этим конечно сложно.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

                  Как раз их и использовал. Не спасло.

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
            Rev. 5   Проголосовать: нравится +5 Проголосовать: не нравится

            Интересная штука. Расследование привело к следующему. std::atan2 в GNU C++ определён как шаблон:

              using ::atan2;
            
              inline float
              atan2(float __y, float __x)
              { return __builtin_atan2f(__y, __x); }
            
              inline long double
              atan2(long double __y, long double __x)
              { return __builtin_atan2l(__y, __x); }
            
              template<typename _Tp, typename _Up>
                inline
                typename __gnu_cxx::__promote_2<
                typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value
            				    && __is_arithmetic<_Up>::__value,
            				    _Tp>::__type, _Up>::__type
                atan2(_Tp __y, _Up __x)
                {
                  typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
                  return atan2(__type(__y), __type(__x));
                }
            

            В данном примере _Tp = int и _Up = int. __enable_if просто делает проверку и возвращает тот же тип. А вот __promote_2 — это

              template<typename _Tp, typename _Up>
                struct __promote_2
                {
                private:
                  typedef typename __promote<_Tp>::__type __type1;
                  typedef typename __promote<_Up>::__type __type2;
            
                public:
                  typedef __typeof__(__type1() + __type2()) __type;
                };
            

            , где так же _Tp = int и _Up = int. Результат вызова __promote2 есть тип результата std::atan2. Так как сумма двух интов тоже int, то получается, что std::atan2<int, int>() возвращает int!

            В самом деле, если в данном примере добавить касты или явно вызвать std::atan2<double, double>, то вывод одинаковый.

            UPD: OK, всё-таки std::tr1::is_same<__typeof__(std::atan2(a, 0)), double>::value = true, так что проблема где-то в другом месте. Однако вышеприведённые хаки всё равно работают.

            UPD2: Проглядел самое главное:

              template<typename _Tp, bool = std::__is_integer<_Tp>::__value>
                struct __promote
                { typedef double __type; };
            

            Так что весь пост ни о чём.

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          VS2005 и g++ 4.6.1 (MinGW).

»
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

что за мода пошла — гнать на компиляторы

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится +7 Проголосовать: не нравится

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

»
13 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Раз пошла такая пьянка зашёл вопрос про компиляторы, спрошу:

В C++ я не особо силён, и не так давно у меня возникла проблема: один и тот же код на С++, используя компилятор GNU C++, получает Accepted, а при использовании MS C++ — неправильный ответ на тесте 8, причём дома я использую Visual Studio Express 2010, там всё работает как надо.

Код: GNU C++ (1644554) и MS C++ (1644555).

В чём причина?

  • »
    »
    13 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится +5 Проголосовать: не нравится

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

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Компиляторы по-разному реагируют на попытку считать число, не помещающееся в int. MinGW превращает его в 231 - 1. В MS C++ происходит обычное переполнение. В данном случае поведение MinGW крайне нелогично. Так что Accepted на нем можно считать ошибкой. Надо сначала проверять длину строки, а потом уже переводить в число.

»
13 лет назад, # |
  Проголосовать: нравится +12 Проголосовать: не нравится

На самом деле, мораль, скорее, такова: всегда используйте сравнение с EPS (ну или MSVC), вещественные числа в MinGW — странная вещь.

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится +9 Проголосовать: не нравится

    Очень странная, если честно, мораль. В компараторах обычно не так просто использовать сравнение с EPS, чтобы не нарушить его транзитивность.

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится

      Мне не приходилось сортировать числа, которые расположены в цепочку с шагом <EPS. Так что обычно ничего страшного, но помнить об этом, конечно, стоит.

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится +9 Проголосовать: не нравится

        А мне приходилось :( Это на самом деле очень большая проблема, которая приводит к непредсказуемым последствиям.

        Ну и вообще, вычисления с плавающей запятой -- это тот еще фан, надо всегда держать ухо в остро. Вот хороший пример непредсказуемого поведения, https://github.com/Kontakter/Cpp-examples/blob/master/trouble_with_double/main.cpp. Кстати на моем текущем ноутбуке работает правильно, а вот на паре удаленных машинок нет :)

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Если компилировать без оптимизаций, сюрприза никакого нет, правда? ;-) На доступных мне компах по крайней мере не проявилось. По-моему, это все-таки спецэффект оптимизатора.

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Да, без оптимизации скорее всего проблем не будет. Спецэффект состоит в том (как я его понимаю), что большинство FPU производит вычисления в 128-битном регистре, а выгружает оттуда только первые 64 бита. Компилятор все оптимизирует так, что ничего не выгружает, а сразу печатает результат, поэтому мы получаем в итоге единицу :)

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Спецэффект с atan2 и std::atan2 проявляется и при -O0

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Кстати, да. Ведь сравнения сами по себе выполняются с погрешностью. Значит, что бы мы не делали, все равно будут строгие сравнения, которые верны в обе стороны. Мне вот интересно, а MinGW тьюринг-полный?

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится +12 Проголосовать: не нравится

        Мне вот интересно, а MinGW тьюринг-полный?

        А причем тут вообще это?

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится -18 Проголосовать: не нравится

          Возможно ли, что глюков в MinGW достаточно, что в нем нельзя реализовать любую программу, которую можно реализовать на машине Тьюринга?

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится +29 Проголосовать: не нравится

            Ну brainfuck на нём, наверное, всё же будет работать, что как-бы намекает ;)

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится +26 Проголосовать: не нравится

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится +14 Проголосовать: не нравится

        Конечно, не Тьюринг полный. Доступная для адресации лента конечна. Какая тут полнота по Тьюрингу может быть...

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится +5 Проголосовать: не нравится

      Не соглашусь.

      Сейчас все строго объясню:

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

      Математически это можно записать так: такой что

      1. |x - y| > 2·ε означает неравество

      2. |x - y| < ε означает равенство.

      3. Чисел таких, что ε ≤ |x - y| ≤ 2·ε не существует.

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

      • »
        »
        »
        »
        13 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        Я согласен, при таких условиях все отлично будет.

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    По идее сравнение идет на аппаратном уровне и от компилятора ну никак не может зависеть

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится -13 Проголосовать: не нравится

      На визуалке не проявляется почему-то.

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

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

»
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

Сколько будет (atan2(1,0) < atan2(1,0))? Правильный ответ — 0, и это нормально. Сколько будет (atan2(1,0) < atan2(1,0))+(atan2(1,0) < atan2(1,0))? Правильный ответ — 2, и это странно...

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится +35 Проголосовать: не нравится
    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится

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

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Ещё в том же могут помочь соответствующие опции/прагмы компиляторов, например, -ffloat-store в GNU C, /fp:strict в MSVC. В Java для этого есть ключевое слово strictfp.

»
13 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

Вот смотрю я на очередную подобную тему, и задаюсь вопросом: а сталкиваются ли с подобными проблемами (баги компилятора) программисты на Java? Конечно, баги есть везде. Но хочется по факту.

P.S.: так же я замечал, что во многих случаях реализация STL в g++ немного быстрее, нежели в MS. Так же, константа увеличения вектора при перераспределении памяти в g++ меньше (AFAIK золотое сечение против удвоения в MS). Бывали случаи, когда некоторое решение на g++ заходило, а на компиляторе MS — давало TL/ML. Так что ответ на вопрос "слать в g++ или в MSVC++" imho достаточно неоднозначен...

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Сталкиваются... Почитайте обсуждение.

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Посылка 1 Посылка 2 Вот два одинаковых кода, разница лишь в типе массива, в одном это Integer[], в другом int[], с int[] проходит 65 тестов, с Integer всего 30. Буду благодарен если какой-нибудь знаток Java скажет мне в чём проблема.

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится +7 Проголосовать: не нравится

      Например, == для Integer работает не так, как вы думаете.

    • »
      »
      »
      13 лет назад, # ^ |
      Rev. 3   Проголосовать: нравится +7 Проголосовать: не нравится

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

      • »
        »
        »
        »
        13 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        Т.е. если я использую Integer, то нужно использовать свой компаратор, где вместо == будет equals, так я понимаю?

        UPD не о том подумал, всё ясно уже, спасибо.

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          используйте == для сравнения указателей, для сравнения объектов есть equals, CompareTo и др. по вкусу, и в зависимости от того что вам нужно

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    В g++ вектор растет в два раза -- только что проверил. В VS в презентации STL говорил, что у них растет в 1.5. Студии проверить нету.

    Я сам хоть локально и пишу на g++, отправляю всегда в студии, потому что I64d.

»
13 лет назад, # |
  Проголосовать: нравится +27 Проголосовать: не нравится

… это не g++, это minGW.

Возможно, на Codeforces еще и Windows стоит Да ладно

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    CF тестят 12 серверов. Почему бы 3-4 из них не сделать линуксовыми?

    • »
      »
      »
      13 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +4 Проголосовать: не нравится

      Зачем?

      1. Производительность понизиться сильно. Сабмиты под MS VC++ не смогут тестироваться на линуксовых серверах и наоборот.

      2. Я думаю, несмотря на то, что Codeforces написан на Java, проблем с переносом всего на linux будет очень много, да и времени это потребует.

      3. Какой именно дистрибутив выбрать?

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        1. Не смогут, но можно подобрать пропорцию, чтоб разница была несущественна. Можно балансировать нагрузку с помощью java и python посылок
        2. Странный вывод. Перенести надо лишь одну функцию безопасного запуска программы. Все остальное должно быть и так кроссплатформенным.
        3. Вот нашли проблему!
        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится +8 Проголосовать: не нравится

          Ты не ответил на главный вопрос. Зачем это делать вообще? Тогда уже нужны и FreeBSD, Mac OS X сервера.

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится -8 Проголосовать: не нравится

            Я и не говорю, что в этом особо много смысла. Просто если уж писать g++ 4.6.*, то это должно работать также, как мой g++ той же версии, как мне кажется.

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
            Проголосовать: нравится +1 Проголосовать: не нравится

          Кстати, в питоне может быть разница между виндой и линуксом. Под 64-битными никсами будет работать 64-битная арифметика на интах, а под виндой — все равно длинка. Подозреваю что в Java тоже приколы есть.

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Например, для того, чтобы не было таких долгоиграющих фейспалмов.

        http://bit.ly/Ik3B5w

        • »
          »
          »
          »
          »
          13 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится +16 Проголосовать: не нравится

          Не понимаю. Как еще вывести long long в С++ через printf на Windows? Ну то есть тогда будет так "Выводите через %lld, если ваш сабмит достанется инвокеру на линуксе и %I64d если винде".

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            А при чём тут windows вообще?

            Если будут Linux-сервера, то на них пусть идут сабмиты по gcc.

            • »
              »
              »
              »
              »
              »
              »
              13 лет назад, # ^ |
                Проголосовать: нравится +24 Проголосовать: не нравится

              Я не понимаю почему упомянутая фраза про "%I64d" является фейспалмом. Это наоборот, хорошо. А то если на каком-нибудь соревновании забыть проверить это на пробном туре, можно получить лишнию посылку.

              • »
                »
                »
                »
                »
                »
                »
                »
                13 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                Она является фейспалмом потому, что в случае посылки на нормальный gcc она имеет мало смысла. Если решение тестируется мной локально на gcc, то и удалённо от него необходимо ожидать такого же поведения. Имхо.

                По "не забыть на пробном туре": так может просто ко всем задачам уже приписывать разные нюансы компиляторов, систем и прочего? Чтобы не забыть проверить на пробном туре.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                    Проголосовать: нравится +8 Проголосовать: не нравится
                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                    Проголосовать: нравится +6 Проголосовать: не нравится

                  И?

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

                  Если реализация gcc под Windows крива, это значит, что тестироваться решения должны на тех системах, где реализация адекватна.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                  Rev. 2   Проголосовать: нравится -6 Проголосовать: не нравится

                  Я, наоборот, абсолютно против костылей.

                  По-моему, переводить часть серверов Codeforces на linux — это костыли.

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

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                    Проголосовать: нравится +3 Проголосовать: не нравится

                  Еще раз. Я не предлагаю переводить часть CF серверов на linux. Я просто не понимаю, зачем мне надо наколоться пару раз, а потом извращаться с дефайнами и запуском просто для того, чтобы узнать настоящее название компилятора?

          • »
            »
            »
            »
            »
            »
            13 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Как еще вывести long long в С++ через printf на Windows?

            %lld естественно. Компиляторами Microsoft, Intel, etc. При чем тут Windows или не Windows вообще. Тут вся проблема в кривом MinGW.

            • »
              »
              »
              »
              »
              »
              »
              13 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              Причём и сам MinGW уже давно понимает %lld.

              • »
                »
                »
                »
                »
                »
                »
                »
                13 лет назад, # ^ |
                  Проголосовать: нравится +6 Проголосовать: не нравится

                Давно — это с какой версии, если не секрет?

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                    Проголосовать: нравится +5 Проголосовать: не нравится

                  Судя по списку изменений файла, обрабатывающего вызовы printf и др., то уже с июля 2008 года (в самой первой ревизии уже есть обработка случая ll). Это соответствует версии mingw-rt >= 3.15.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

                  А то есть все настолько плохо. Есть ветка g++ которая принимает одно, а есть которая принимает другое.

                  MinGW которое поставляется с msys например не принемает lld

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

                  MinGW не поставляется с MSYS, это MSYS поставляется с MinGW.

                  Имеется в виду i686-pc-msys-gcc (версия которого аж 3.4.4)? Я попробовал и он тоже правильно выводит числа типа 123456789123456789LL или 18446744073709551615ULL с помощью %lld/%llu.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  13 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

                  У меня версия 4.6.1 выводит верно, но выдаёт warning, что некорректный placeholder

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится +8 Проголосовать: не нравится

      И тестить на рандомном инвокере?

»
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Интересным вариантом для *никсоидов была бы кросс-компиляция *никсовым портом mingw32 и последующий запуск под wine ("костыль на костыле и костылем погоняет", так сказать). Попробую, как прийду домой.

»
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

А кто-нибудь знает, на mingw ровно реализован fseek? Codeblocks при наведении на fseek выдает странный define. И вот это настораживает...