Здравствуйте, Sir Wiz, Вы писали:
SW>>>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.
E>>В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел.
SW>(*pInt & 0xff000000) >> 24;
SW>Не будет, говорите? Это для x86.
Никогда — это значит никогда. В том числе для x86, конечно.
SW>Borland и VC сделают тут две разные вещи.
Что ж, если какой-то компилятор работает неправильно (что, правда, еще надо показать), стоит отправить bug report.
SW>А ещё есть вариации с low/big endian... Я не нашел в стандарте ни слова о требованиях к побитному расположению в памяти интегральных типов.
Стандарт, по большей части, внутреннее представление типов не регламентирует. А при чем тут это?
Здравствуйте, Sir Wiz, Вы писали:
Ш>>>>Второй вариант правильный. Первый будет работать только на некоторых платформах. E>>А почему, кстати?
SW>Например, отсутствие физической возможности обратиться к адресу не кратному 2^n, где n > 0.
Гм-гм... Вы, как и я, предполагаете, что типы BYTE и byte в примерах WinterMute — это синонимы unsigned char?
Здравствуйте, elcste, Вы писали:
SW>>>>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора.
E>>>В приведенном выше коде — surprise! — никогда не будет правого сдвига отрицательных чисел. E>
SW>>(*pInt & 0xff000000) >> 24;
SW>>Не будет, говорите? Это для x86.
E>Никогда — это значит никогда. В том числе для x86, конечно.
Извольте, вот пояснение с картинками
int * pInt = new int;
*pInt = -1;
*pInt = *pInt & 0xFF000000; // *pInt == -16777216
*pInt >> 24; // Правый сдвиг отрицательного числа.
SW>>Borland и VC сделают тут две разные вещи. E>Что ж, если какой-то компилятор работает неправильно (что, правда, еще надо показать), стоит отправить bug report.
Правильно работает. В соответствии со стандартом делает что хочет. В частности, VC сохраняет знак, Borland — нет.
SW>>А ещё есть вариации с low/big endian... Я не нашел в стандарте ни слова о требованиях к побитному расположению в памяти интегральных типов.
E>Стандарт, по большей части, внутреннее представление типов не регламентирует. А при чем тут это?
К тому, что побитные операции в принципе не переносимы. Поправьте, если это не так.
Отгадка: Подвыражение *pInt имеет тип int, тогда как подвыражение *pInt & 0xff000000 в 32-разрядных компиляторах под x86 имеет тип unsigned int.
Литература: Читать про integer literals, integral promotions и usual arithmetic conversions.
SW>К тому, что побитные операции в принципе не переносимы. Поправьте, если это не так.
Побитовые операции над беззнаковыми типами в принципе переносимы. Побитовые операции над знаковыми типами имеют ряд опасных особенностей (которые, кстати, лучше описаны в стандарте C99, нежели C++).
Здравствуйте, Sir Wiz, Вы писали:
E>>Гм-гм... Вы, как и я, предполагаете, что типы BYTE и byte в примерах WinterMute — это синонимы unsigned char?
SW> Да, точно подмечено. Не знаю, честно говоря. Но, видимо, да.
То есть вопрос о выравнивании исчерпан. Правильно я понимаю?
Здравствуйте, elcste, Вы писали:
E>Отгадка: Подвыражение *pInt имеет тип int, тогда как подвыражение *pInt & 0xff000000 в 32-разрядных компиляторах под x86 имеет тип unsigned int.
Здравствуйте, Sir Wiz, Вы писали:
SW>Здравствуйте, JakeS, Вы писали:
JS>>>>господа, елси уж для вашей программы существенна разница в скорости выполнения команды mov — Пишите нужный участок в чистом ассемблере, однозначно будет быстрее.
SW>>>Как правило интеловский, например, компилятор генерирует более качественный код. Так как учитывает особенности работы процессора.
JS>>В данном случае никакие особенности процессора ни при чем. речь идет всего лишь о доступе к участкам памяти. Очевидно что быстрее всего единственная операция mov регистр, адрес и в дальнейшем работа только с регистрами. Причем совершенно без разницы какой процессор.
SW>Не претендую на профессианлизм в этом вопросе, но как же конвейерная оптимизация?
Конвейерная оптимизация — это то, поведение чего никто не гарантирует и, кроме создателей, предсказать не может. Короче как морская свинка и не свинка, и не морская, но работает быстрее.
Ш>>Второй вариант правильный. Первый будет работать только на некоторых платформах.
SW>Нет, второй вариант тоже неправильный. Правый сдвиг отрицательных чисел определяется реализацией компилятора. SW>Кроме того не гарантируется, что размер типа int будет равен 4-м байтам.
Как сказал автор, int 32 разрядный. Сколько он при этом занимает на самом деле байт -- не имеет значения.
Сдвигов отрицательных чисел в этом примере не будет. Потому что константе 0xFF000000, например, на машине, где int 32 разрядный, будет назначен тип unsigned int.
Здравствуйте, JakeS, Вы писали:
SW>>Не претендую на профессианлизм в этом вопросе, но как же конвейерная оптимизация?
JS>Конвейерная оптимизация — это то, поведение чего никто не гарантирует и, кроме создателей, предсказать не может. Короче как морская свинка и не свинка, и не морская, но работает быстрее.
AFAIK, поведение конвейеров описано в интеловской документации.
И в компиляторе Intel реализована оптимизация именно под их процессоры, учитывающая работу конвейеров, HT, и времени выполнения команд.
Пожалуй единственное, известное мне место, где приходится писать на ассемблере — MMX/SSE/SSE2/SSE3. Например при умножении матриц компилятор не всегда может сам векторизовать.