Есть ли компилятор C, который не может это скомпилировать? - PullRequest
19 голосов
/ 30 ноября 2008

Я какое-то время зависал в своем профилировщике, пытаясь понять, как ускорить работу обычного парсера журналов, который был узким местом при разборе даты, и я пробовал различные алгоритмы, чтобы ускорить процесс.

То, что я попробовал, было самым быстрым для меня, также было наиболее читабельным, но потенциально нестандартным C.

Это хорошо работало в GCC , icc и моем действительно старом и требовательном компиляторе SGI. Поскольку это вполне читаемая оптимизация, где она не делает то, что я хочу?

static int parseMonth(const char *input) {
    int rv=-1;
    int inputInt=0;
    int i=0;

    for(i=0; i<4 && input[i]; i++) {
        inputInt = (inputInt << 8) | input[i];
    }

    switch(inputInt) {
        case 'Jan/': rv=0; break;
        case 'Feb/': rv=1; break;
        case 'Mar/': rv=2; break;
        case 'Apr/': rv=3; break;
        case 'May/': rv=4; break;
        case 'Jun/': rv=5; break;
        case 'Jul/': rv=6; break;
        case 'Aug/': rv=7; break;
        case 'Sep/': rv=8; break;
        case 'Oct/': rv=9; break;
        case 'Nov/': rv=10; break;
        case 'Dec/': rv=11; break;
    }
    return rv;
}

Ответы [ 13 ]

0 голосов
/ 30 ноября 2008

Мне бы очень хотелось, чтобы профилирование показало this - это ваше самое существенное узкое место, но в любом случае, если вы собираетесь извлечь что-то подобное, используйте объединение вместо 50 циклических инструкций и сдвиг. Вот небольшой пример программы, я оставлю ее вам, чтобы она вписалась в вашу программу.

/* union -- demonstrate union for characters */

#include <stdio.h>

union c4_i {
    char c4[5];
    int  i ;
} ;

union c4_i ex;

int main (){
    ex.c4[0] = 'a';
    ex.c4[1] = 'b';
    ex.c4[2] = 'c';
    ex.c4[3] = 'd';
    ex.c4[4] = '\0';
    printf("%s 0x%08x\n", ex.c4, ex.i );
    return 0;
}

Вот пример вывода:

bash $ ./union
abcd 0x64636261
bash $ 
0 голосов
/ 30 ноября 2008

Если не учитывать размер машинного слова, ваш компилятор может преобразовать input [i] в ​​отрицательное целое число, которое будет просто устанавливать верхние биты inputInt с помощью или операции, поэтому я предлагаю вам явно указать сигнатуру переменных char.

Но поскольку в США никто не заботится о 8-м бите, это, вероятно, не проблема для вас.

0 голосов
/ 30 ноября 2008

Тот факт, что четырехсимвольная константа эквивалентна конкретному 32-разрядному целому числу, является нестандартной функцией, часто встречающейся в компиляторах для компьютеров под управлением Windows и Mac (и PalmOS, AFAICR). *

В этих системах четырехсимвольная строка обычно используется в качестве тега для идентификации фрагментов файлов данных или в качестве идентификатора приложения / типа данных (например, «APPL»).

Для разработчика удобнее то, что они могут хранить такую ​​строку в различных структурах данных, не беспокоясь об окончании нулевого байта, указателях и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...