Помимо очевидного (-Os -s
), выравнивание функций по наименьшему возможному значению, которое не приведет к сбою (я не знаю требований к выравниванию ARM), может сжать несколько байт на функцию.
-Os
должен уже отключить функции выравнивания, но это может по-прежнему иметь значение по умолчанию, например 4 или 8. При выравнивании, например 1 можно использовать с ARM, что может сэкономить несколько байтов.
-ffast-math
(или менее абразивный -fno-math-errno
) не будет устанавливать ошибку и избегает некоторых проверок, что уменьшает размер кода. Если, как и большинство людей, вы все равно не читаете errno, это вариант.
Правильное использование __restrict
(или restrict
) и const
устраняет избыточные нагрузки, делая код быстрее и меньше (и более корректным). Правильная маркировка чистых функций как таковых исключает вызовы функций.
Включение LTO может помочь, и, если оно недоступно, компиляция всех исходных файлов в двоичный файл за один раз (gcc foo.c bar.c baz.c -o program
вместо компиляции foo.c
, bar.c
и baz.c
для объектных файлов, а затем связывание) будет иметь аналогичный эффект. Он делает все видимым оптимизатору за один раз, возможно, позволяя ему работать лучше.
-fdelete-null-pointer-checks
может быть опцией (обратите внимание, что обычно она включается с любым «O», но не для встроенных целей).
Размещение статических глобальных переменных (надеюсь, у вас их не так много, но все же) в структуре может уничтожить много накладных расходов их инициализации. Я узнал об этом, когда писал свой первый загрузчик OpenGL. При наличии всех указателей на функции в структуре и инициализации структуры с помощью = {}
генерируется один вызов memset
, в то время как при инициализации указателей «обычный путь» генерирует сто килобайт кода, просто чтобы установить каждый из них на ноль по отдельности.
Избегайте использования статических локальных переменных, подобных дьяволу (нет проблем с типами POD). Gcc будет инициализировать потокобезопасные статические локальные локальные конструкторы, если вы не скомпилируете с -fno-threadsafe-statics
, который связывает в много дополнительного кода (даже если вы вообще не используете потоки).
Использование чего-то вроде libowfat вместо обычного crt может значительно уменьшить ваш двоичный размер.