Как создать собственный тип данных для оперирования шестнадцатиричными значениями?
Нужен тип данных в котором можно указывать символы 0 - 9 и A - F и при этом они автоматически воспринимались как шестнадцатиричные значения.
Пример практического применения:
В теле программы будет производиться запись в LPT порт на ассемблере
mov DX, PortAddr
mov AL, Value
out DX, AL
Сам ассемблер хавает любые значения(и это очень удобно) и 888 в десятичной и 378Н в шестнадцатиричной системах.
А вот когда пытаешся обернуть это в функцию возникают потуги, нет подходящего типа для переменной PortAddr.
Можно конечно пересчитывать адреса в десятичную систему, но как вы помните приложение rtss, и не хочется тратить драгоценные такты процессора.
Были попытки использовать enum, но к сожалению не компилится так как мне нужно(видимо имена перечисления не могут начинаться с цифр). Был бы идеальный вариант: enum HEXWORD {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F};
Буду рад любым соображениям по данному поводу.
Так же были попытки использовать union, но это похоже не совсем то что мне нужно.
А про typedef я вообще молчу, зачем переименовывать тип, и в итоге использовать тот же самый?
unsigned short portnumber = 0xAABB;
unsigned char portnumber = 0xAA;
><
Для компилятора и программы нет разници хоть арабскими цифрами записывай хоть римскими - на выходе получишь BIN представление числа, не нужно ничего никуда переводить.
Но нужно чтоб без 0х.....
Например будет написана вот такая функция:
RtWriteLPTPort(????? PortAddr, BYTE Value)
{
_asm
{
mov DX, PortAddr
mov AL, Value
out DX, AL
}
}
При использовании(если PortAddr типа unsigned short):
RtWriteLPTPort(378(ну или например требуется написать 37с), 255); в ассемблер попадает 17А, то есть нужно передавать не 378, а 888. Это не приемлимо, пересчёт в программе(если таких мест накопится много) делать дорого.
К сожалению с си пока не очень дружу(всё время на паскале ковырялся), концепция в голове есть а как реализовать не знаю.
Пока мне видится такой подход:
членами типа могут быть символы 30 - 39 и 41 - 46, и каждому символу присвоенно шестнадцатиричное значение.
Ну както объявить что:
char 30 = 0x0
char 31 = 0x1
char 32 = 0x2
...
char 41 = 0xA
char 42 = 0xB
...
Вот чтото такое нужно закодить. Тип это будет или класс может быть. Пусть это будет чем угодно, главное чтоб в итоге можно было несколько символов писать, и они воспринимались как одно целое(ну как в том же short, например 12 воспринимается как 12, а не как отдельные 1 и 2)
Если ты напишешь RtWriteLPTPort(0x378,255) то туда и упадет 378H
Если ты напишешь RtWriteLPTPort(888,255) перевод из dec в hex будет только на этапе __компиляции__(!!!) 1 раз а не регулярно при выполнении программы
Понимаете, например программу которую я пишу возможно будет использовать еще ктото кроме меня.
И возможно запись будет и по другим адресам
Не хотелось бы выводить сообщение типа:
"Выберите устройство для записи, и переведите его адрес в калькуляторе в десятичное представление или введите как есть добавив впереди 0 с крестиком". Тем более что калькулятор работать не сможет в момент работы программы(винда виснет намертво)
Сейчас это запись в LPT, потом это может быть запись в USB или сетевой адаптор.
Адреса берутся с диспетчера устройств, который для LPT выдаёт примерно следующее:
Диапазон ввода/вывода (I/O) 0378 - 037F
Диапазон ввода/вывода (I/O) 0778 - 077B
...
...
Win32 API мне не доступны. С их помощью наверное можно было получить адреса и не морочиться со всякими переводами а просто передать по назначению.
printf("Введите адрес:");
scanf("%x",&portaddr);
А в чём принципиальное ограничение сохранить 378НЕХ и так же использовать как НЕХ без перевода в DEC и потом обратно ???
Нифига!
в переменной теперь если ввести 378 будет 1101111000 !!! Компьютер работает в двоичной системе, хоть и оперирует с байтами. А вот при выводе на экран для удобочитаемости число переводится в десятичную систему.
Давай теперь кодить будем на машинном коде, реч то про языки высокого уровня.
Ты меня окончательно запутал. В итоге int это BIN или DEC ???
Жалко что для удобочитаемости НЕХ не добавили
речь же идет о программе реального времени - какая венда?????
помоему ты сам себя запутал -
var
A: CARDINAL;
begin
A := 1024;
Edit1.Text := IntToStr(A);
значением строки становится почемуто 1024, а не 10000000000.
Но в памяти ведь лежит 10000000000, откуда берётся 1024 это ведь ктото пересчитывает(для удобочитаемости).
Почему бы по точно такой же логике не добавить возможность пересчета в HEX.
Так же был бы тип специальный:
var
A: ????????;
begin
A := 400; // В память кладётся 10000000000
Edit1.Text := IntToStr(A); // Выводится 400
var
A: CARDINAL;
begin
A := 1024;
Edit1.Text := IntToStr(A);
значением строки становится почемуто 1024, а не 10000000000.
Но в памяти ведь лежит 10000000000, откуда берётся 1024 это ведь ктото пересчитывает(для удобочитаемости).
Почему бы по точно такой же логике не добавить возможность пересчета в HEX.
:facepalm:
А теперь приоткрою тебе тайну: в делфи есть IntToHex еще :D
var
A: CARDINAL;
begin
A := 1024;
Edit1.Text := IntToStr(A); //1024
Edit1.Text := IntToHex(A,1); //400
И именно эти функции переводят то что в памяти в удобочитаемый вид.
А теперь внимание полный вынос мозга: itoa
Пять баллов! :)))
BIN и DEC имеют значение как раз приведённых выше примерах, при конвертации числа в строку.
Теперь следует определиться, у вас аргументы - строки или числа?!
Если строки, то конвертируйте в строки, если числа, то хватить морочить себе и другим голову, пользуйтесь как есть - ничего править/конвертировать не нужно!
Это я попал в заблуждение из за удобства которое для меня сделали.
По умолчанию подразумевается DEC(а я воспринял это как привязку типа к DEC).
Если бы для любой ситемы счисления обязательно нужно было указывать что работаем именно с ней, я бы не попал в такое заблуждение.
Теперь я понял что создавать ещё один числовой тип не имеет смысла. Тот что есть удовлетворяет потребности.
Теперь только один вопрос:
Можно ли использовать typedef, и уже для нового типа назначить что по умолчанию работаем в HEX(чтоб писать не 0х378, а 378)? Или у самого встроенного типа изменить это "удобство"?
int main()
{
int a=011;
int b=0x11;
int c=11;
std::cout<<"a="<<a<<std::endl;
std::cout<<"b="<<b<<std::endl;
std::cout<<"c="<<c<<std::endl;
return 0;
}
Ты можешь только
а: смириться с тем что в мире принята 10-я система счисления и писать 0x когда пишешь hex
б: улететь в джунгли и всместе с аборигенами развивать собственное общество с 16-ричной системой счисления
в: написать макросы для перевода
#define h(a) 0x##a
int main()
{
int a=011;
int b=0x11;
int c=11;
int d=h(11);
std::cout<<"a="<<a<<std::endl;
std::cout<<"b="<<b<<std::endl;
std::cout<<"c="<<c<<std::endl;
std::cout<<"d="<<d<<std::endl;
return 0;
}
г: не парить нас а вступить в комитет стандартизации C++ и потр##ть мозг им
Класс написать можно, но плохо, придется задавать значения строками, тк. компилятор 12F3 откажется принимать, а F123 вообще скажет что нет такой переменной только "123F", что по геморности и производительности никогда не окупится и по длине записи будут те же 2 символа дополнительных
Я бы еще раз подумал на счет первых двух вариантов, они наиболее реальны
Придётся смириться, и писать по стандартам.
Нет сил уже никие макросы писать, буду вводить в десятичной системе.