#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 ) ;
}
}