int main () { pid_t pid = getpid (); printf ("Hi. My pid is %d\n", pid); return 0; }
Всё замечательно и хорошо, но встаёт вопрос: правильно ли использовать %d для типа pid_t? Для size_t? Для всех прочих типов typedef’нутых от чего-нибудь целочисленного?
На x86 практически всё по 32-бита и вопросов не возникает: хочется вывести размер массива, который size_t? Пишем %d. А на x86_64 уже всё чуть сложнее. Например, size_t уже 64 бита, а %d выковыривает из стека лишь 32-битную переменную. Как в такой ситуации написать программу, которая одинаково хорошо будет компилироваться и на 32-битной платформе, и на 64-битной?
Варианта напрашивается два: либо использовать ifdef’ы и форматную строку менять. Но это неудобно. Либо всё, что может вызывать вопросы кастить к (long long) и выводить как %lld. (Кстати даже на x86 я подчастую сумлевался писать %d или %u, но это как правило некритично).
Ах, да, в качестве третьего варианта, можно забить на C и использовать C++ с его перегруженными функциями/операторами. Но это неинтересно.
Собственно, интересно, как бы так покрасивее решить эту проблему разнобитовой совместимости.
ps. я как-то натыкался на статейку, в которой, насколько я помню, было приемлимое решение, но мне она тогда была неинтересна, и я её по диагонали тогда глазом пробежал, а сегодня уже и не вспомнить как это делать. И статью не найти. :(
Последние комментарии
- OlegL, 17 декабря в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
Здоровый ночной сон принёс решение :)
Лучше, по-моему, не выйдет.
Почему не просто
?
И если есть сомнения можно явно сделать:
Потому что, если речь идёт о 64-битной платформе, то второй аргумент printf’а, положит в стек четыре байта, а printf, увидев %ld, прочитает 8. На 32-битной, по-моему всё сработает, там вроде sizeof (int) == sizeof (long).
А касты мне не нравятся. Потому что если следовать идее до конца, придётся всё (pid_t, size_t, off_t и пр) конвертать в 64-бита внезависимости от платформы.
Я могу ошибаться, то на 64-битной pid_t должен быть 8 байт.
Вот глянул исходники ядра, 32-й он на обоих. На мой взгляд не правильно, решать использовать дополнительные #define, об этом позаботились уже разработчики ядра и надо просто правильно ставить модификатор. Так для pid_t он должен быть «%d».
А с size_t, что делать?
Он как раз long и должно быть «%ld».
Размер long’а различен для 64-битных linux и windows. size_t же, наверное, одинаков.
size_t = unsigned long на каждой архитектуре. Грубо говоря, size_t — это тип адреса, его malloc() возвращает. На 64-битной платформе size_t = 64 бита.
Тогда я чего-то непонимаю в этой жизни. Вот ссылочка: http://www.ibm.com/developerworks/library/l-port64.html, там есть табличка размеров целочисленных типов для разных «data models». Если твоё высказывание есть истина, то к чему тогда там эта табличка? Точнее столбец озаглавленный LLP64, где sizeof(long)!=sizeof(void*)
При этом, я видел табличку соответствия размеров типов в 64-битном лине и 64-битной венде. Ссылку мне искать лень, но я точно помню что они различались в размерах типа long.
http://www.osdev.org/wiki/X86-64
См. Models used by 64bit OSs
Да. Вендовс пользует LLP64. Но ведь, я как рассуждаю: sizeof(size_t) должен равен размеру адреса, иначе нафига весь этот сыр-бор с 64-мя битами. То есть sizeof(size_t)==8. Но в виндовс, в LLP64, sizeof(long)==4 => sizeof(long)!=sizeof(size_t).
Но
Противоречие. :)
Ну да, подменил понятия немного. Я Unix имел ввиду.