Здравствуйте, pepsicoca, Вы писали:
P>1. Как портабельно определить, на какой платформе (big-endian или little-endian) запущена программа?
мне почему-то всегда казалось, что endianness фиксируется при компиляции
то бишь это все сделать через ifdef
расскажите на каких именно платформах вы планируете запускать свое приложение?
Re: как портабельно узнать порядок байт в Юникоде?
В общем-то достаточно узнать это при компиляции, а не проверять при выполнении, т.к. скомпилированный код всегда заточен под определенный порядок байт (по крайней мере, мне сложно представить обратное).
В бусте есть такая штука — http://www.boost.org/doc/libs/1_50_0/boost/detail/endian.hpp. Сам я не пользовался, но по идее должно работать на большинстве платформ.
Re: как портабельно узнать порядок байт в Юникоде?
P>Добрый день.
P>Есть программа на С++, которая должна работать на разных платформах с Юникодом.
P>В том числе платформы различаются по параметру big-endian <-> little-endian.
P>Также программа должна работать с данными big-endian на платформе little-endian и с данными little-endian на платформе big-endian.
P>Чтобы все это осуществить, необходимо знать, на какой платформе сейчас запущена программа: на платформе big-endian или платформе little-endian.
P>Вопрос:
P>1. Как портабельно определить, на какой платформе (big-endian или little-endian) запущена программа?
P>Спасибо.
Здравствуйте, pepsicoca, Вы писали:
P>Есть программа на С++, которая должна работать на разных платформах с Юникодом. P>1. Как портабельно определить, на какой платформе (big-endian или little-endian) запущена программа?
P>Спасибо.
Можно использовать htons()/ntohs() или ntohl()/htonl() для преобразования порядка байт.
Re[2]: как портабельно узнать порядок байт в Юникоде?
Здравствуйте, AleksandrN, Вы писали:
P>>Есть программа на С++, которая должна работать на разных платформах с Юникодом. P>>1. Как портабельно определить, на какой платформе (big-endian или little-endian) запущена программа?
AN>Можно использовать htons()/ntohs() или ntohl()/htonl() для преобразования порядка байт.
На big-endian платформе эти функции ничего не делают, т.к. там порядок байт уже сетевой. Могут возникнуть неприятные сюрпризы.
Гораздо проще накидать макросню для конвертации, благо макросов таких полный интернет.
И кстати да: узнать, не big-endian ли у нас платформа, можно тупо в лоб в рантайме:
Здравствуйте, chemey, Вы писали:
C>Здравствуйте, AleksandrN, Вы писали:
P>>>Есть программа на С++, которая должна работать на разных платформах с Юникодом. P>>>1. Как портабельно определить, на какой платформе (big-endian или little-endian) запущена программа?
AN>>Можно использовать htons()/ntohs() или ntohl()/htonl() для преобразования порядка байт.
C>На big-endian платформе эти функции ничего не делают, т.к. там порядок байт уже сетевой. Могут возникнуть неприятные сюрпризы. C>Гораздо проще накидать макросню для конвертации, благо макросов таких полный интернет.
C>И кстати да: узнать, не big-endian ли у нас платформа, можно тупо в лоб в рантайме:
C>if( htons(1234) == 1234 )
Увы, это не портабельно, так как htons это функция из состава WinAPI.
C>{ C> // Big-endian machine C>} C>else C>{ C> // Little-endian machine C>}
C>Хотя это уже излишество нехорошее: порядок байт известен уже при компиляции.
Похоже, что на этапе компиляции нельзя узнать, на какой платформе (big-endian или little-endian) запущена программа.
Если в рантайме, то, действительно, можно выгрузить константу размером больше байта в память и прочитать ее побайтно, то есть попробовать что-то в этом роде:
Здравствуйте, pepsicoca, Вы писали:
P>Здравствуйте, chemey, Вы писали:
C>>Здравствуйте, AleksandrN, Вы писали:
P>>>>Есть программа на С++, которая должна работать на разных платформах с Юникодом. P>>>>1. Как портабельно определить, на какой платформе (big-endian или little-endian) запущена программа?
AN>>>Можно использовать htons()/ntohs() или ntohl()/htonl() для преобразования порядка байт.
C>>На big-endian платформе эти функции ничего не делают, т.к. там порядок байт уже сетевой. Могут возникнуть неприятные сюрпризы. C>>Гораздо проще накидать макросню для конвертации, благо макросов таких полный интернет.
C>>И кстати да: узнать, не big-endian ли у нас платформа, можно тупо в лоб в рантайме:
C>>if( htons(1234) == 1234 )
P>Увы, это не портабельно, так как htons это функция из состава WinAPI.
C>>{ C>> // Big-endian machine C>>} C>>else C>>{ C>> // Little-endian machine C>>}
C>>Хотя это уже излишество нехорошее: порядок байт известен уже при компиляции.
P>Похоже, что на этапе компиляции нельзя узнать, на какой платформе (big-endian или little-endian) запущена программа.
P>Если в рантайме, то, действительно, можно выгрузить константу размером больше байта в память и прочитать ее побайтно, то есть попробовать что-то в этом роде:
P>
Здравствуйте, pepsicoca, Вы писали:
P>Здравствуйте, chemey, Вы писали:
C>>И кстати да: узнать, не big-endian ли у нас платформа, можно тупо в лоб в рантайме:
C>>if( htons(1234) == 1234 )
P>Увы, это не портабельно, так как htons это функция из состава WinAPI.
Здрасьте, приехали.
Эта функция входит в состав POSIX, а следовательно, реализована на всех UNIX-платформах. В Солярисе, в Линуксе, в *BSD, в AIX и прочих HPUX она имеется (проверено электроникой).
В WinAPI, действительно, имеются свои функции, работающие с сокетами (всякие WSAAsyncSelect), но что касается htons() — она реализована в винде ровно так же, как и в юниксах. Она абсолютно автономна и ей не требуется загруженная Winsock DLL:
The htons function does not require that the Winsock DLL has previously been loaded with a successful call to the WSAStartup function.
C>>Хотя это уже излишество нехорошее: порядок байт известен уже при компиляции.
P>Похоже, что на этапе компиляции нельзя узнать, на какой платформе (big-endian или little-endian) запущена программа.
Если программа собрана для big-endian машины (например, SPARC), ты просто не сможешь ее запустить на little-endian машине (даже если это тот же SPARC в режиме little-endian). На этапе загрузки вылетит ошибка при проверке заголовка исполняемого файла (практически все современные форматы исполняемых файлов содержат поле, в котором указывается архитектура и/или endianness процессора, на котором надо программу исполнить). Даже если твой бинарь не содержит заголовка (типа com-программы под DOS), запустить ее не получится: первая же инструкция, обращающаяся к памяти по абсолютному адресу, обратится "не туда".
На практике же пропасть между big-endian и little-endian машинами такова, что ты ни при каких обстоятельствах не сможешь напрямую запустить программу, скомпилированную под big-endian платформу, на little-endian процессоре. Это возможно только под эмулятором а-ля QEMU (но при этом твоя программа, фактически, исполняется в big-endian среде).
P>
P>wchar_t wch=0x100; /* Big-Endian Solaris 64-bit: wch=0x00 00 01 00 */
P>char* cptr=(char*)(&wch); /* Big-Endian Solaris 64-bit: cptr[0] = 00 */
P>if(cptr[0]==0) cout<<"little-endian"; else cout<<"big-endian"; /* Да шо ви говогитя? */
P>
Это плохой, негодный код.
Это под виндой wchar_t гарантированно двухбайтный. Под UNIX'ами wchar_t может быть и двухбайтным, и четырехбайтным, и даже восьмибайтным ему быть никто не запрещал. Твоя проверка вернет little-endian для любой платформы, у которой wchar_t не двухбайтовый.
Если уж проверять байтики в рантайме, то проверяй последний:
Здравствуйте, chemey, Вы писали:
C>Здравствуйте, pepsicoca, Вы писали:
P>>Здравствуйте, chemey, Вы писали:
C>>>И кстати да: узнать, не big-endian ли у нас платформа, можно тупо в лоб в рантайме:
C>>>if( htons(1234) == 1234 )
P>>Увы, это не портабельно, так как htons это функция из состава WinAPI.
C>Здрасьте, приехали. C>Эта функция входит в состав POSIX, а следовательно, реализована на всех UNIX-платформах. В Солярисе, в Линуксе, в *BSD, в AIX и прочих HPUX она имеется (проверено электроникой).
Пишем под платформы без ОС, по голому железу для микроконтроллеров.
C>В WinAPI, действительно, имеются свои функции, работающие с сокетами (всякие WSAAsyncSelect), но что касается htons() — она реализована в винде ровно так же, как и в юниксах. Она абсолютно автономна и ей не требуется загруженная Winsock DLL:
C>
C>The htons function does not require that the Winsock DLL has previously been loaded with a successful call to the WSAStartup function.
C>>>Хотя это уже излишество нехорошее: порядок байт известен уже при компиляции.
P>>Похоже, что на этапе компиляции нельзя узнать, на какой платформе (big-endian или little-endian) запущена программа.
C>Если программа собрана для big-endian машины (например, SPARC), ты просто не сможешь ее запустить на little-endian машине (даже если это тот же SPARC в режиме little-endian). На этапе загрузки вылетит ошибка при проверке заголовка исполняемого файла (практически все современные форматы исполняемых файлов содержат поле, в котором указывается архитектура и/или endianness процессора, на котором надо программу исполнить). Даже если твой бинарь не содержит заголовка (типа com-программы под DOS), запустить ее не получится: первая же инструкция, обращающаяся к памяти по абсолютному адресу, обратится "не туда".
+5
Хорошая идея — запустить бинарник от х86 на Спарке.
А если серьезно, то речь конечно же шла о переносимости кода до трансляции.
C>На практике же пропасть между big-endian и little-endian машинами такова, что ты ни при каких обстоятельствах не сможешь напрямую запустить программу, скомпилированную под big-endian платформу, на little-endian процессоре. Это возможно только под эмулятором а-ля QEMU (но при этом твоя программа, фактически, исполняется в big-endian среде).
P>>
P>>wchar_t wch=0x100; /* Big-Endian Solaris 64-bit: wch=0x00 00 01 00 */
P>>char* cptr=(char*)(&wch); /* Big-Endian Solaris 64-bit: cptr[0] = 00 */
P>>if(cptr[0]==0) cout<<"little-endian"; else cout<<"big-endian"; /* Да шо ви говогитя? */
P>>
C>Это плохой, негодный код. C>Это под виндой wchar_t гарантированно двухбайтный. Под UNIX'ами wchar_t может быть и двухбайтным, и четырехбайтным, и даже восьмибайтным ему быть никто не запрещал. Твоя проверка вернет little-
Восьмибайтный Юникод это просто праздник для производителей памяти.
На сайте Юникод.орг написано, что юникод четырехбайтный. И в четырехбайтном-то 99% кодовой таблицы пустует.
endian для любой платформы, у которой wchar_t не двухбайтовый.
C>Если уж проверять байтики в рантайме, то проверяй последний: C>
Если под микроконтроллеры, то это еще один аргумент в пользу определения порядка байт на этапе компиляции, т.к. наверняка при этом получится более компактный и быстрый код, чем код, умеющий и так, и так. К тому же при запуске на каждой конкретной платформе один из вариантов кода всегда будет гарантированно бездействовать.
P>Пишем под платформы без ОС, по голому железу для микроконтроллеров.
Re[7]: как портабельно узнать порядок байт в Юникоде?
Здравствуйте, angry.andrew, Вы писали:
AA>Если под микроконтроллеры, то это еще один аргумент в пользу определения порядка байт на этапе компиляции, т.к. наверняка при этом получится более компактный и быстрый код, чем код, умеющий и так, и так. К тому же при запуске на каждой конкретной платформе один из вариантов кода всегда будет гарантированно бездействовать.
P>>Пишем под платформы без ОС, по голому железу для микроконтроллеров.
1. Не думаю, что буст странслируется (к примеру) иаром.
2. Не думаю, что перечисление всех известных автору на какой-то момент архитектур в макросе это хорошая идея для портабельного определения чего-либо.
3. Код не бездействует. Задача например такая: программу кормят юникодным файлом, созданным на машине с be или le системой. При этом программа сама может работать на be или le машине. Получается 4 варианта. Для корректной работы нужно при входе свопить байты юникода или не свопить байты юникода, в зависимости от. Какая система у файла можно узнать по BOM. А какая система у машины можно узнать в рантайме как тут уже предложили.
Re[8]: как портабельно узнать порядок байт в Юникоде?
Здравствуйте, pepsicoca, Вы писали:
P>Здравствуйте, angry.andrew, Вы писали:
AA>>Если под микроконтроллеры, то это еще один аргумент в пользу определения порядка байт на этапе компиляции, т.к. наверняка при этом получится более компактный и быстрый код, чем код, умеющий и так, и так. К тому же при запуске на каждой конкретной платформе один из вариантов кода всегда будет гарантированно бездействовать.
P>>>Пишем под платформы без ОС, по голому железу для микроконтроллеров.
P>1. Не думаю, что буст странслируется (к примеру) иаром.
Не обязательно тянуть весь буст в проект.
Никто ж не запрещает изучить бустовые исходники в одном конкретном месте и сделать похоже. Там достаточно свободная лицензия.
P>2. Не думаю, что перечисление всех известных автору на какой-то момент архитектур в макросе это хорошая идея для портабельного определения чего-либо.
Тебе шашечки или ехать? Если шашечки, то можно долго строить конструкции из макросов и детекторов концеватости в рантайме, и вести философские беседы о преимуществах и недостатках разных подходов.
Если тебе ехать, на big-endian машине определяй макрос BIG_ENDIAN, на little-endian — макрос LITTLE_ENDIAN (прямо в командной строке компилятора -DBIG_ENDIAN=1). В коде используй соответствующие ифдефы. Ты ведь знаешь, надеюсь, под какую систему собираешь в данный конкретный момент?
P>3. Код не бездействует. Задача например такая: программу кормят юникодным файлом, созданным на машине с be или le системой. При этом программа сама может работать на be или le машине. Получается 4 варианта. Для корректной работы нужно при входе свопить байты юникода или не свопить байты юникода, в зависимости от. Какая система у файла можно узнать по BOM. А какая система у машины можно узнать в рантайме как тут уже предложили.
Ващета получается только два варианта: свопить (концеватость различная) или не свопить (совпадает).
В рантайме имеет смысл определять те вещи, которые могут поменяться в процессе выполнения или между запусками программы. Ты что же, собрался один и тот же бинарь попеременно запускать то на big-endian, то на little-endian архитектуре?
Бзззззззжжжжж
Re: как портабельно узнать порядок байт в Юникоде?
Здравствуйте, pepsicoca, Вы писали:
P>Также программа должна работать с данными big-endian на платформе little-endian и с данными little-endian на платформе big-endian.
P>Чтобы все это осуществить, необходимо знать, на какой платформе сейчас запущена программа: на платформе big-endian или платформе little-endian.
А как вы собираетесь определять endian данных?
По большому счету, вам совершенно незачем знать, каков endian платформы и данных, а надо знать, совпадают они или нет.
Стандартный способ называется BOM, и при его использовании вы, собственно, и получаете ответ на этот вопрос — даже не зная endian'а платформы.
Re[9]: как портабельно узнать порядок байт в Юникоде?
Здравствуйте, chemey, Вы писали:
C>Здравствуйте, pepsicoca, Вы писали:
P>>Здравствуйте, angry.andrew, Вы писали:
AA>>>Если под микроконтроллеры, то это еще один аргумент в пользу определения порядка байт на этапе компиляции, т.к. наверняка при этом получится более компактный и быстрый код, чем код, умеющий и так, и так. К тому же при запуске на каждой конкретной платформе один из вариантов кода всегда будет гарантированно бездействовать.
P>>>>Пишем под платформы без ОС, по голому железу для микроконтроллеров.
P>>1. Не думаю, что буст странслируется (к примеру) иаром.
C>Не обязательно тянуть весь буст в проект.
Буст это такая вещь, что она сама тянет за собой все, что там есть.
C>Никто ж не запрещает изучить бустовые исходники в одном конкретном месте и сделать похоже. Там достаточно свободная лицензия.
P>>2. Не думаю, что перечисление всех известных автору на какой-то момент архитектур в макросе это хорошая идея для портабельного определения чего-либо.
C>Тебе шашечки или ехать? Если шашечки, то можно долго строить конструкции из макросов и детекторов концеватости в рантайме, и вести философские беседы о преимуществах и недостатках разных подходов. C>Если тебе ехать, на big-endian машине определяй макрос BIG_ENDIAN, на little-endian — макрос LITTLE_ENDIAN (прямо в командной строке компилятора -DBIG_ENDIAN=1). В коде используй соответствующие ифдефы. Ты ведь знаешь, надеюсь, под какую систему собираешь в данный конкретный момент?
P>>3. Код не бездействует. Задача например такая: программу кормят юникодным файлом, созданным на машине с be или le системой. При этом программа сама может работать на be или le машине. Получается 4 варианта. Для корректной работы нужно при входе свопить байты юникода или не свопить байты юникода, в зависимости от. Какая система у файла можно узнать по BOM. А какая система у машины можно узнать в рантайме как тут уже предложили.
C>Ващета получается только два варианта: свопить (концеватость различная) или не свопить (совпадает).
Два варианта исхода их четырех возможных комбинаций.
C>В рантайме имеет смысл определять те вещи, которые могут поменяться в процессе выполнения или между запусками программы. Ты что же, собрался один и тот же бинарь попеременно запускать то на big-endian, то на little-endian архитектуре?
Мечта — работать как можно меньше.
В том числе чтобы все само работало и мне не приходилось вспоминать о макросе, который определяет be или le.
Если бы такой макрос был в системе и включался автоматом, то было бы хорошо.
Если такого макроса нет, то флаг в рантайме лучше, чем свой макрос.
Один раз при старте поднял флажок и потом все процедурки на него смотрят и делают что надо.
Ну будет лишний иф, сколько там этих лишних ифоф, никто не считает.
Re[2]: как портабельно узнать порядок байт в Юникоде?
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, pepsicoca, Вы писали:
P>>1. Как портабельно определить, на какой платформе (big-endian или little-endian) запущена программа?
U>мне почему-то всегда казалось, что endianness фиксируется при компиляции
Не только. Есть ещё endianness потока данных. Например, я долго не мог понять, почему некоторые TIFF-смотрелки умеют показывать ту классическую картинку с космонавтом в космосе, а некоторые — не могут. Потом покурил формат TIFF, написал свою гляделку и понял, что у картинки с космонавтом — MAC'овский endianness
Re: как портабельно узнать порядок байт в Юникоде?
Здравствуйте, pepsicoca, Вы писали:
P>Есть программа на С++, которая должна работать на разных платформах с Юникодом. P>В том числе платформы различаются по параметру big-endian <-> little-endian.
Ребята, не страдайте фигнёй. Извне юникодные данные должны приходить в UTF-8. А он endian-нейтральный.