Страницы

Поиск по вопросам

воскресенье, 12 января 2020 г.

Кросплатформенный код на C, теоретические проблемы

#c #кроссплатформенность


Понимаю что вопрос дурацкий, но тем не менее :) В каких случаях неверно утверждение:
"если код на pure C, использующий только стандартные библиотеки, собирается и работает
под linux-32, linux-64 и win-32, то он без дополнительных мер соберётся и корректно
заработает под win64"?

В принципе ответ очевиден: например, в тех случаях, где есть завязка на разрядность,
совмещённая с "ифдеф виндовс". Но есть практические примеры не таких очевидных вещей?
    


Ответы

Ответ 1



Как уже было сказано выше, многое зависит не только от платформы, но и от компилятора - часто именно от компилятора. Для разрешения ситуаций с размерами и разрядностью иногда создаются внутренние типы, фактический смысл которых зависит от платформы. Так например у Apple CGFloat в 32-битной системе это float, а в 64-битной - double. Для пущей совместимости могу посоветовать собирать проект одним и тем же компилятором на разных платформах.

Ответ 2



Ну, например вы используете тип long, который имеет разный размер на разных платформах, и приводите его к другому типу (к указателю) OS arch size Windows IA-32 4 bytes Windows Intel 64 4 bytes Windows IA-64 4 bytes Linux IA-32 4 bytes Linux Intel 64 8 bytes Linux IA-64 8 bytes Mac OS X IA-32 4 bytes Mac OS X Intel 64 8 bytes Visual C, Win32: sizeof(char)=1 sizeof(wchar_t)=2 sizeof(short)=2 sizeof(int)=4 sizeof(long)=4 sizeof(long long)=8 sizeof(void*)=4 sizeof(size_t)=4 Visual C, Win64: sizeof(char)=1 sizeof(wchar_t)=2 sizeof(short)=2 sizeof(int)=4 sizeof(long)=4 sizeof(long long)=8 sizeof(void*)=8 sizeof(size_t)=8 GCC on 32 platform: sizeof(char)=1 sizeof(wchar_t)=4 sizeof(short)=2 sizeof(int)=4 sizeof(long)=4 sizeof(long long)=8 sizeof(void*)=4 sizeof(size_t)=4 GCC on 64 platform: sizeof(char)=1 sizeof(wchar_t)=4 sizeof(short)=2 sizeof(int)=4 sizeof(long)=8 sizeof(long long)=8 sizeof(void*)=8 sizeof(size_t)=8

Ответ 3



Довольно часто код полагается на undefined behaviour, и таким образом зависит от конкретной реализации компилятора. Популярной ошибкой является вызов метода, не использующего локальные переменные, по NULL-указателю. Это может сработать на некоторых платформах, но по стандарту это имеет право привести к чему угодно. То же относится к переполнению знакового целого. GNU toolchain под интеловской платформой доопределяет поведение в этом случае, но другие компиляторы — нет. Более тонкая ошибка: чтение неинициализированной переменной есть UB по стандарту. Очень многие забывают это, считая, что она будет содержать «какое-то там значение», и ничего страшного в обращении к ней нет. Однако, на платформе IA64 (Itanium) это может привести к крешу.

Комментариев нет:

Отправить комментарий