Прежде всего, проблема заключается не в if
; как вы видели, gcc
видит через if
и проходит мимо 30
прямо на printf
.
Теперь gcc
имеет некоторую логику для обработки особых случаев printf
(в частности, делает оптимизацию printf("something\n")
и даже printf("%s\n", "something")
к puts("something")
), но она весьма специфична и не идти дальше; printf("Hello %s\n", "world")
, например, остается как есть. Хуже того, любой из вариантов выше без конечной новой строки остаются нетронутыми, даже если они могут быть преобразованы в fputs("something", stdout)
.
Я полагаю, что это сводится к двум основным проблемам:
два случая выше, чрезвычайно легко шаблоны для реализации и случаются довольно часто, но в остальном, вероятно, это редко стоит усилий; если строка является постоянной и производительность важна, программист может позаботиться об этом легко - на самом деле, если производительность printf
имеет решающее значение, он не должен полагаться на такую оптимизацию, которая может нарушиться при малейшем изменении формата строка.
Если вы спросите меня, даже оптимизаторы puts
выше уже «идут за точками стиля», вы действительно не получите серьезных результатов ни в чем, кроме искусственных тестовых случаев.
Когда вы начинаете выходить за пределы области %s\n
, printf
- это минное поле, потому что оно имеет сильную зависимость от среды выполнения; в частности, многие спецификаторы printf
(к сожалению) затронуты языковой версией, плюс есть лебедка специфичных для реализации особенностей и спецификаторов (и gcc
может работать с printf
от glibc, musl, mingw/msvcrt, ...- и во время компиляции вы не можете вызывать целевое время выполнения C - подумайте, когда вы выполняете кросс-компиляцию).
Я согласен с тем, что этот простой случай %d
, вероятно, безопасен, но я могу понять, почему они, вероятно, решили избежать чрезмерной умности и выполнять самые тупые и безопасные оптимизации здесь.
Для любознательных читателей, here, где эта оптимизация фактически реализуется; как вы можете видеть, функция соответствует ограниченному числу очень простых случаев (и GIMPLE в сторону, не сильно изменилась с this nice article, изложив их, было написано). Кстати, источник на самом деле объясняет, почему они не могут реализовать вариант fputs
для случая, не связанного с новой чертой (нет простого способа ссылаться на глобальный stdout
на этом этапе компиляции).
'gcc' не делает (не может ..?) Предсказать вывод' printf'. – LPs
@LPs AFAIK, он вызывает вызовы printf() с вызовами puts() и putchar(), где это возможно. – Mitsos101
@ Mitsos101 только с * известными константами времени компиляции *. То, что вы смотрите в своем коде, может быть определено только путем его запуска. Легко для вас сделать в своей голове - менее легко для компилятора. – adelphus