Более эффективный способ проверить номер и добавить в шестнадцатеричный код соответственно

#c #performance

Вопрос:

Должен быть более эффективный способ сделать это, верно?

Единственная разница в строках заключается в том, что шестнадцатеричный код увеличивается на 0x000A0 и какие данные должны быть равны.

 void lineprint(const char *string, int data) { 
    // Add 'A0'(0x000A0) to '0xB8000' to get to another line on the screen
    if(data == 0) {volatile char *video = (volatile char*)0xB8000; lineprint_print(video,string);}
    if(data == 1) {volatile char *video = (volatile char*)0xB80A0; lineprint_print(video,string);}
    if(data == 2) {volatile char *video = (volatile char*)0xB8140; lineprint_print(video,string);}
    if(data == 3) {volatile char *video = (volatile char*)0xB81E0; lineprint_print(video,string);}
    if(data == 4) {volatile char *video = (volatile char*)0xB8280; lineprint_print(video,string);}
    if(data == 5) {volatile char *video = (volatile char*)0xB8320; lineprint_print(video,string);}
    if(data == 6) {volatile char *video = (volatile char*)0xB83C0; lineprint_print(video,string);}
}
 

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

1. Конечно, вы могли бы просто вычислить местоположение памяти напрямую? if (data >= 0 amp;amp; data <= 6) { volatile char *video = (volatile char*)(0xB8000 data * 0xa0); lineprint_print(video,string); }

2. Если вы сделаете data без подписи, вы даже можете пропустить проверку на >= 0 наличие …

3. Эффективность, возможно, не самая большая проблема с этим кодом. Его нужно изменить, потому что это просто плохой код — неэлегантный и недоступный; Я сомневаюсь, что для 6-строчного дисплея производительность является большой проблемой. Выберите решение, которое легче поддерживать и понимать, а не то, которое обязательно каким — то образом «оптимально» — хотя было бы нетрудно превзойти это.

4. Тот факт, что вы, возможно, разрабатываете какую-то операционную систему, не делает это вопросом операционной системы- избыточные теги удалены.

Ответ №1:

Это можно сделать с помощью простого вычисления адреса на основе data :

 void lineprint(const char *string, int data) { 

    if (data >= 0 amp;amp; data <= 6) {
        volatile char *video = (volatile char*)(0xB8000   0xA0 * data);
        lineprint_print(video,string);
    } else {
        // bad input handling
    }
}
 

Альтернативно это можно сделать с помощью массива, если адреса расположены не так хорошо:

 void lineprint(const char *string, int data) { 
    uint32_t addresses[] = {0xB8000, 0xB80A0, /* The rest.... */};

    if (data >= 0 amp;amp; data <= 6) {
        volatile char *video = (volatile char*)addresses[data];
        lineprint_print(video,string);
    } else {
        // bad input handling
    }
}
 

Примечание: Этот массив может быть создан static для повышения производительности среды выполнения (то есть, чтобы избежать повторной инициализации при каждом вызове функции) и const , как ожидается, не будет изменен.

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

1. Я бы сделал data без подписи, чтобы не нужно было явно проверять data >= 0 .

2. @Aconcagua Конечно, но зависит от того, откуда это изначально

3. Не совсем, если исходное значение было

4. @Aconcagua Вы, вероятно, правы, не могу придумать случая, чтобы это провалилось. Но оставим это на рассмотрение ОПС

5. @RamdomlyRandom Аконкагуа означает определять void lineprint(const char *string, unsigned int data)

Ответ №2:

Очевидно, что это может быть рассчитано арифметически, что может повысить эффективность работы с размером кода, но для эффективности времени выполнения может быть предпочтительнее поисковая таблица, особенно если поисковая таблица мала, как в данном случае:

 void lineprint( const char* str, unsigned line ) 
{
    volatile char* vaddr[] = { (volatile char*)0xB8000, 
                               (volatile char*)0xB80A0,
                               (volatile char*)0xB8140,
                               (volatile char*)0xB81E0,
                               (volatile char*)0xB8280,
                               (volatile char*)0xB8320,
                               (volatile char*)0xB83C0 } ;

    if( line < sizeof(vaddr) / sizeof(*vaddr) )
    {
        lineprint_print( vaddr[line], str ) ;
    }
}
 

Даже без арифметической зависимости исходный код тестируется data шесть раз, когда каждое условие является взаимоисключающим — только одно может быть истинным. switch В любом случае более подходящей была бы обзорная таблица или a.

Арифметическое решение может выглядеть так:

 #define MAX_LINE 6
#define LINE_LENGTH 0xA0
#define VBASE ((volatile char*)0xB8000)

void lineprint( const char* str, unsigned line ) 
{
    if( line <= MAX_LINE )
    {
        lineprint_print( VBASE   (line * LINE_LENGTH), 
                         str ) ;
    }
}