|
Программирование >> Перегруженные имена функций и идентификаторы
(используйте определение 8 для CHAR BIT, если нет головного файа <limits.h>: #include <limits.h> /* для CHAR BIT */ #define BITMASK(bit) (1 << ((bit) % CHAR BIT)) #define BITSLOT(bit) ((bit) / CHAR BIT) #define BITSET(ary, bit) ((ary)[BITSLOT(bit)] = BITMASK(bit)) #define BITTEST(ary, bit) ((ary)[BITSLOT(bit)] & BITMASK(bit)) Как наилучшим образом определить число установленных бит, соответствующих определенному значению? Решение этой и многих других проблем из области битоверчения можно ускорить и сделать более эффективным с помощью таблиц перекодировки. Как повысить эффективность работы программы? Тема эффективности, очень часто затрагиваемая, не так важна как многие склонны думать. Большая часть кода в большинстве программ не влияет на время исполнения. Если время, занимаемое каким-то участком кода, мало по сравнению с общим временем исполнения, то для этого участка гораздо важнее простота и мобильность, чем эффективность. (Помните, что компьютеры очень, очень быстры и даже неэффективный участок кода может выполняться без видимой задержки). Печально известны попытки предсказать горячие точки программы. Когда эффективность программы имеет значение, важно использовать профилировщики для определения тех участков программы, которые заслуживают внимания. Часто основное время выполнения поглощается периферийными операциями, такими как ввод/вывод и выделение памяти, которые можно ускорить с помощью буферизации и хеширования. Для небольших участков программы, критичных в смысле эффективности, жизненно важно выбрать подходящий алгоритм; микрооптимизация этого участка менее важна. Многие часто предлагаемые приемы по увеличению эффективности (вроде замены операции сдвига умножением на степень двойки) выполняются автоматически даже неизощренными компиляторами. Неуклюжие попытки оптимизации способны так увеличить размер программы, что ее эффективность упадет. Правда ли, что применение указателей более эффективно, чем применение массивов? Насколько замедляет программу вызов функции? Быстрее ли ++i чем i = i + 1? Точные ответы на эти и многие другие похожие вопросы, конечно же, зависят от процессора и применяемого компилятора. Если знать это необходимо, придется аккуратно определить время выполнения тестовых программ. (Часто различия столь незначительны, что потребуются сотни тысяч повторений, чтобы их увидеть. Если есть возможность, посмотрите ассемблерный листинг, выдаваемый компилятором, чтобы убедиться в различной трансляции двух претендующих на первенство альтернатив). Обычно быстрее продвигаться по большим массивам с помощью указателей, чем с помощью индексов, однако есть процессоры, для которых справедливо обратное. Хотя вызовы функций и увеличивают время выполнения, сами функции настолько повышают модульность и простоту понимания программы, что едва ли полезно от них отказываться. Прежде чем переписывать выражения типа i=i+1, вспомните, что имеете дело с компилятором Си, а не с программируемым калькулятором. Любой приличный компилятор будет одинаково транслировать i+=1; i=i+1. Использовать i+=1 ии i=i+1 - вопрос стиля, а не эффективности. Почему не выполняется такой фрагмент: char *p = Hello, world! ; p[0] = tolower(p[0]); Стринговые константы не всегда можно модифицировать, за исключением случая, когда ими инициализируется массив. Попробуйте: char a[] = Hello, world! ; (Для компиляции старых программ некоторые компиляторы имеют ключ, который управляет возможностью модификации стринговых констант.) Моя программа аварийно завершается еще до выполнения! (если использовать отладчик, то видно, что смерть наступает еще до выполнения первой инструкции в main) Видимо, у вас один или несколько очень больших (более килобайта) локальных массивов. Во многих системах размер стека фиксирован, а операционные системы, в которых осуществляется динамическое выделение стековой памяти, (например, UNIX) могут быть введены в заблуждение, когда размер стека резко увеличивается. Часто предпочтительнее объявить большие массивы типа static (если, конечно, каждый раз при рекурсивном вызове не требуется свежий массив). Что означают сообщения Segmentation violation и Bus error ? Это значит, что программа пытается получить доступ к несуществующей или запрещенной для нее области памяти. Это постоянно происходит из-за неинициализированных или неверно инициализированных указателей, по вине malloc или, может быть, scanf. Моя программа аварийно завершается, очевидно, при выполнении malloc, но я не вижу в ней ничего плохого К несчастью, очень легко разрушить внутренние структуры данных, создаваемые malloc, а возникающие проблемы могут быть трудны для отладки. Чаще всего проблемы возникают при попытке записать больше данных, чем может уместиться в памяти, выделенной malloc; особенно распространена ошибка malloc(strlen(s)) вместо strlen(s) + 1. Другие проблемы включают освобождение указателей, полученных не в результате выполнения malloc, или попытки применить функцию realloc к нулевому указателю. Существует несколько отладочных пакетов, чтобы помочь отследить возникающие при применении malloc проблемы.Есть у кого-нибудь комплект тестов для Си компилятора? Где достать грамматику Си для программы YACC? Самая надежная - конечно же грамматика из стандарта ANSI. Другая грамматика, подготовленная Джимом Роскиндом (Jim Roskind), находится на ics.uci.edu в директории pub/*grammar*. Одетый в поть, работающий образец ANSI грамматики (принадлежащий Джефу Ли(Jeff Lee)) находится на
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |