Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.90/198: Рейтинг темы: голосов - 198, средняя оценка - 4.90
21 / 19 / 6
Регистрация: 25.11.2017
Сообщений: 708

Что за тип данных uint32_t?

30.07.2019, 22:34. Показов 40456. Ответов 171
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Это без знаковый int, который занимает 32 бита. А вот t, что значит?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.07.2019, 22:34
Ответы с готовыми решениями:

Как побитово скопировать uint32_t в float, минуя при этом выделения uint32_t в оперативную память
Всем привет, недавно заинтересовал такой вопрос ниже. Как ПОБИТОВО скопировать uint32_t в float, минуя при этом выделения uint32_t в...

Что такое рекурсивный тип данных? Что такое конструкция рекурсивного типа?
Что такое рекурсивный тип данных? Что такое конструкция рекурсивного типа?

Скажите пожалуйста, что это за тип данных?!
int **allocate2D(int rows, int cols) { int **arr2D; int i, j; arr2D = (int**)malloc(rows*sizeof(int*)); for(i=0;...

171
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
18.08.2019, 18:19
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Это в глаза бросается!
var1->var2 тоже в глаза бросается, если специально приглядываться. А вот если не знать куда смотреть, что так, что сяк, пролетит мимо глаз.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
И еще раз предлагаю начинать вводить новые ветки спора с обоснования каким же они боком к изначальной теме. Совместимость нескольких языков по ABI никакого отношение к "совместимости с исходным кодом Си" не имеет.
"Совместимость с исходным кодом Си" которую тащит стандарт, это и есть экспорт заранее скомпилированных библиотек. Сами библиотеки могут быть хоть на Фортране, C++ компилятор их код не смотрит, ему все равно.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Интерпретация памяти float как целого числа это UB или ID?
Это UB под названием "Strict aliasing".
Given an object with effective type T1, using an lvalue expression (typically, dereferencing a pointer) of a different type T2 is undefined behavior, unless:

T2 and T1 are compatible types.
T2 is cvr-qualified version of a type that is compatible with T1.
T2 is a signed or unsigned version of a type that is compatible with T1.
T2 is an aggregate type or union type type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union).
T2 is a character type (char, signed char, or unsigned char).
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Тут производительность явно будет ниже (о чем я уже писал), но например можно так:
Я так и не понял зачем была нужна эта простыня PORT_OFF.
C++
1
2
3
DDRA|=usedBits;//выставляем сразу все нужные ножки в режим вывода
PORTA&=~usedBits;//сбрасываем нужные биты
PORTA|=seg_nums[num];//выводим нужную маску
DDRA как я понимаю, можно вынести за пределы функции. Или ножки постоянно меняют назначение с вывода на ввод?
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Через регистр передали индекс элемента в массиве. Адрес начала откуда возьмете?
Адрес прочитаю из другого регистра. Или там и mov 16-битовые регистры копировать не умеет?
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
18.08.2019, 20:25
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
void * присутствует в С с самого первого стандарта. "void* не было вообще" - это эпоха туманных эскизов языка.
Хорошо-хорошо, я вам верю. Этот вопрос меня совершенно не интересует и я не хочу спорить на эту тему.
Цитата Сообщение от Renji Посмотреть сообщение
"Совместимость с исходным кодом Си" которую тащит стандарт, это и есть экспорт заранее скомпилированных библиотек.
А, то есть у вас термин "совместимость с языком" означает не то, что у остальных людей. Для вас "совместимость с языком" это "реализация общего ABI, которое к языку никак не привязано". Так бы и сказали.
Цитата Сообщение от Renji Посмотреть сообщение
Это UB под названием "Strict aliasing".
Тем не менее, это может использоваться для быстрого вычисления обратного квадратного корня. То есть тот самый случай, когда компилятор не должен запрещать (мешать - может) программисту стрелять себе в ногу в угоду производительности.
Цитата Сообщение от Renji Посмотреть сообщение
Я так и не понял зачем была нужна эта простыня PORT_OFF.
Вы определились уже какую задачу решаете? Код с кучей PORT_OFF / PORT_ON был для совсем произвольного распределения выводов по портам. Просто поверьте, что заводить несколько (заранее неизвестное количество) масок на несколько портов невыгодно ни по скорости, ни по памяти. Если не хотите просто поверить, попробуйте написать соответствующий код. Если напишу я по своему разумению - вы же скажете что имели в виду другое и код из вашей головы должен работать лучше.
Цитата Сообщение от Renji Посмотреть сообщение
DDRA как я понимаю, можно вынести за пределы функции.
Естественно, это же инициализация, а не рабочий режим.
Цитата Сообщение от Renji Посмотреть сообщение
Адрес прочитаю из другого регистра. Или там и mov 16-битовые регистры копировать не умеет?
Архитектура AVR вообще-то 8-битная, так что команд, работающих с регистровыми парами раз-два и обчелся, и у них куча ограничений. Например, movw (16-битный mov) копирует между четырьмя регистровыми парами. adiw (16-битное сложение с числом) работает с 3 или 4 регистровыми парами (точно не помню) и числом от 0 до 63.
Да и занимать целую регистровую пару под начало массива, который нужен где-то раз в вечность (типичный период переключения цифр при динамической индикации - миллисекунды, это очень долго) вряд ли кто-то станет. Что еще хуже, эффективность такого варианта не будет выше, чем обычного.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
18.08.2019, 21:04
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
А, то есть у вас термин "совместимость с языком" означает не то, что у остальных людей. Для вас "совместимость с языком" это "реализация общего ABI, которое к языку никак не привязано". Так бы и сказали.
У меня C++ стандарт из совместимости заявлял только наличие сишных инклудов. Да и те через переходник stdint.h->cstdint. Все остальное пытаетесь списать на совместимость вы, а не стандарт. То что конкретно gcc и сишный Generic в C++-коде скушает это, в который раз повторяю, личная блажь gcc.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Тем не менее, это может использоваться для быстрого вычисления обратного квадратного корня. То есть тот самый случай, когда компилятор не должен запрещать (мешать - может) программисту стрелять себе в ногу в угоду производительности.
Strict aliasing именно в угоду производительности и введен. Когда вы читаете значение по указателю, компилятор пытается запомнить прочитанное в регистре. Но так как *floatPointer=0 могло изменить значение *intPointer, то сохраненное в регистре значение придется выкидывать. Именно поэтому в стандарте и написано что нельзя писать в *floatPointer, а читать потом из *intPointer.

Ради 1% квадратных корней достаточно завести модификатор shoot_foot. Сишники же требуют чтоб им дали подобные хаки по умолчанию и плевать что они ломают оптимизацию в 99% кода.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Вы определились уже какую задачу решаете? Код с кучей PORT_OFF / PORT_ON был для совсем произвольного распределения выводов по портам. Просто поверьте, что заводить несколько (заранее неизвестное количество) масок на несколько портов невыгодно ни по скорости, ни по памяти. Если не хотите просто поверить, попробуйте написать соответствующий код.
Да тоже самое что и раньше, с минимальными исправлениями. И еще раз напоминаю, считаем что уж работу с константами времени компиляции компилятор оптимизирует. А не пытается скомпилировать if-ы уже во время компиляции превращающиеся в if(0).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//биты маски 0-7 - биты PORTA. 8-15 - PORTB 16-23 - PORTC 24-31 - PORTD
constexpr auto segmentA=1;//нулевая ножка PORTA
constexpr auto segmentB=1<<20;//пятая ножка PORTC
 
//маска со всеми нужными ножками
constexpr auto usedPorts=0xFF00FF;
 
template<unsigned portID>
std::uint8_t getNumberMask(unsigned number)
{
    constexpr auto shift=portID*8;
    //маски для цифр
    static const std::uint8_t numberList[10]={(segmentA>>shift)&0xFF,
                                          (segmentB>>shift)&0xFF,
                                          (3>>shift)&0xFF,
                                          (4>>shift)&0xFF,
                                          (5>>shift)&0xFF,
                                          (6>>shift)&0xFF,
                                          (7>>shift)&0xFF,
                                          (8>>shift)&0xFF,
                                          (9>>shift)&0xFF,
                                          (10>>shift)&0xFF};
    return numberList[number];
}
 
void showNumber(unsigned number)
{
    //if-ы раскрываются на стадии компиляции
    if(usedPorts&0xFF)
    {
        PORTA&=~(usedPorts&0xFF);
        PORTA|=getNumberMask<0>(number);
    }
    if(usedPorts&0xFF00)
    {
        PORTB&=~((usedPorts>>8)&0xFF);
        PORTB|=getNumberMask<1>(number);
    }
    if(usedPorts&0xFF0000)
    {
        PORTC&=~((usedPorts>>16)&0xFF);
        PORTC|=getNumberMask<2>(number);
    }
    if(usedPorts&0xFF000000)
    {
        PORTD&=~((usedPorts>>24)&0xFF);
        PORTD|=getNumberMask<3>(number);
    }
}
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
19.08.2019, 08:36
Цитата Сообщение от Renji Посмотреть сообщение
Все остальное пытаетесь списать на совместимость вы, а не стандарт.
Пошли по третьему кругу. Вы отрицаете наличие в С++ конструкций, взятых из Си, таких как структуры, сырые указатели, функции с переменным числом аргументов, возможность обратиться к элементу массива как 1["str"], явное приведение типов (не касты)? Если не отрицаете, то зачем оно там есть?
Цитата Сообщение от Renji Посмотреть сообщение
То что конкретно gcc и сишный Generic в C++-коде скушает это
Да оставьте уже расширения в покое! У вас что, травма детства, когда тетрис не смогли скомпилировать майкрософтовсеим компилятором что ли?
Цитата Сообщение от Renji Посмотреть сообщение
Когда вы читаете значение по указателю, компилятор пытается запомнить прочитанное в регистре.
Тут тоже по третьему кругу. Ну вот какое отношение кеширование результатов имеет к реинтерпретации типов?
Цитата Сообщение от Renji Посмотреть сообщение
Но так как *floatPointer=0 могло изменить значение *intPointer, то сохраненное в регистре значение придется выкидывать. Именно поэтому в стандарте и написано что нельзя писать в *floatPointer, а читать потом из *intPointer.
По такой логике нет разницы в типе указателя, *intPointer=0 точно так же могло изменить значение в *intPointer2.
На самом деле проблема в представлении чисел и порядке байтов, именно поэтому UB. Но если программист знает что делает - флаг в руки.
Цитата Сообщение от Renji Посмотреть сообщение
Ради 1% квадратных корней достаточно завести модификатор shoot_foot. Сишники же требуют чтоб им дали подобные хаки по умолчанию и плевать что они ломают оптимизацию в 99% кода.
Как раз ради 1% никто вводить сущность в язык не будет, максимум предложат использовать внешнюю функцию на другом языке. Лучше просто не ломать оптимизацию 100% кода, вводя не обоснованные технически ограничения. Именно проверки всего и вся в угоду безопасности (проверка границ массива, диапазона чисел и т.п.) снижают скорость кода.
Цитата Сообщение от Renji Посмотреть сообщение
constexpr auto segmentB=1<<20;//пятая ножка PORTC
Я еще раз спрашиваю: от сдвига на 80 бит компилятору не поплохеет?
Цитата Сообщение от Renji Посмотреть сообщение
void showNumber(unsigned number)
Для простейшего случая (все на одном порту) ладно, код достаточно небольшой, чтобы даже использование С++ не мешало понять смысл. Также допустим, у компилятора хватит мозгов заинлайнить getNumberMask и выкинуть заведомо ложные if'ы. Тогда результат вашего кода сводится к моему ассемблерному коду.
А если портов больше? Вы выделяете память под N массивов и вынимаете из маску из каждого. А ведь наложение маски это 3 такта: чтение, модификация, запись (in; or/and; out), тогда как работа с одним битом это один такт (cbi/sbi).
Кликните здесь для просмотра всего текста
;подготовка указателя на массив
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ldi ZL, low(numberList0)
ldi ZH, high(numberList0)
;--PORTA
in r16, PORTA
andi r16, ~(1<<3)
out PORTA, r16 ;порты помечены как volatile, так что оптимизировать здесь компилятор права не имеет
add ZL, number
adc XH, r1
ld r17, Z
in r16, PORTA
or r16, r17
out PORTA, r16
;--PORTB
;допустим, добавили ручное кеширование в переменную
in r16, PORTB
andi r16, ~(1<<6)
adiw Z, 10 ;допустим (не уверен, что компилятор догадается) что массивы идут последовательно
ld r17, Z
ori r16, r17
out PORTB, r16
Без ручного кеширования получаем 10 тактов на порт. С ним - 8 тактов. Если расположить массивы во флеше, получится 11 и 9 тактов соответственно.
Вариант на макросах тратит 3 такта на бит, то есть строго 21 такт на все 7 бит:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
;подготовка
ldi ZL, low( seg_codes )
ldi ZH, high( seg_codes )
add ZL, num
adc ZH, r1
ld r16, Z
;SEG_A
cbi PORTA, 3
sbrc r16, 0
  sbi PORTA, 3
;SEG_B
cbi PORTB, 6
sbrc r16, 1
  sbi PORTB, 6
И я еще раз сомневаюсь, что компилятор будет в восторге от 80-битных констант.

Цитата Сообщение от Renji Посмотреть сообщение
PORTA&=~(usedPorts&0xFF);
А если в контроллере нет PORTA? Например, в распространенном ATmega8 или используемых в Ардуине ATmega48-328.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
19.08.2019, 13:17
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Пошли по третьему кругу. Вы отрицаете наличие в С++ конструкций, взятых из Си, таких как структуры, сырые указатели, функции с переменным числом аргументов, возможность обратиться к элементу массива как 1["str"], явное приведение типов (не касты)? Если не отрицаете, то зачем оно там есть?
Еще раз, разжевано. C++ позволяет переопределить механизм управления памятью через механизм аллокаторов. Чтобы кодить эти аллокаторы сырые указатели и нужны. И ответ "Петр Петрович, не выпендривайтесь, слушайте свои Валенки!" не делает аллокаторы механизмом совместимости с Си.
За касты intPointer=doublePointer вам C++ компилятор даст по рукам.
Касты intPointer=(int*)doublePointer банально удобнее километрового reinterpret_cast. Но clang может плеваться на них варнингом.
Тоже самое со struct. С удовольствием его выкинем, когда поля class сделают публичными по умолчанию.

Эллипсисы используются в сигнатуре некоторых экспортируемых сишных функций. Это да, совместимость. В плюсах для того же самого уже есть variadic templates.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
По такой логике нет разницы в типе указателя, *intPointer=0 точно так же могло изменить значение в *intPointer2.
Именно поэтому в Си также ввели ключевое слово restrict.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Я еще раз спрашиваю: от сдвига на 80 бит компилятору не поплохеет?
Если сдвигать std::bitset, то нет. Другой вопрос что к методам std::bitset забыли дописать constexpr, поэтому он не хочет считаться в компил-тайме. Но это проблема именно метода, а не компилятора. Велосипедный аналог строк на двадцать в компил-тайме вполне работает.

По битам - для двух портов 8*2 все равно будет меньше чем 3*7. И сценарий "семь выводов на двух портах" явно более вероятен чем сценарий "семь выводов на семи портах". Если же нужно вот прям на любой сценарий закладываться, то дует switch по usedBits. Макросы опять же не при делах.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//здесь должен был быть std::bitset, но пришлось исправлять его мелкие недоработки
class bitset
{
public:
    static constexpr auto size=32;
 
    constexpr bitset(){}
    constexpr bitset(unsigned shift,unsigned port){data[port]=1<<shift;}
    constexpr bitset operator|(const bitset&value)const
    {
        bitset res;
        for(unsigned pos=0;pos<size;++pos)
            res.data[pos]=data[pos]|value.data[pos];
        return res;
    }
    constexpr std::uint8_t getByte(std::size_t pos)const{return data[pos];}
private:
    std::uint8_t data[size]={0};
};
 
//а то у вас сейчас и сдвиги станут неудобными...
constexpr bitset operator "" _pin(const char*str,std::size_t ){
    return bitset (str[1]-'0',str[0]-'A');
}
 
constexpr bitset segmentA="A3"_pin;//о как я понятно и читаемо сделал!
constexpr bitset segmentB="D1"_pin;
constexpr bitset usedBits=segmentA|segmentB;
 
template<unsigned port>
std::uint8_t getMask(unsigned number)
{
    static const std::uint8_t data[10]={
        (segmentA|segmentB).getByte(port),
        segmentA.getByte(port),
        segmentB.getByte(port),
        1,
        2,
        3,
        4,
        5,
        6,
        7
    };
    return data[number];
}
 
void showNumber(unsigned number)
{
    if(usedBits.getByte(0))
        //с учетом пожеланий о кешировании промежуточных вычислений
        PORTA=(PORTA&~usedBits.getByte(0))|getMask<0>(number);
    if(usedBits.getByte(1))
        PORTB=(PORTB&~usedBits.getByte(1))|getMask<1>(number);
    if(usedBits.getByte(2))
        PORTC=(PORTC&~usedBits.getByte(2))|getMask<2>(number);
    if(usedBits.getByte(3))
        PORTD=(PORTD&~usedBits.getByte(3))|getMask<3>(number);
}
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
А если в контроллере нет PORTA? Например, в распространенном ATmega8 или используемых в Ардуине ATmega48-328.
1) Поставьте заглушку std::uint8_t PORTA, чтоб не пихать в каждую дырку #ifdef. Если никто заглушкой пользоваться не будет, компилятор ее сам уберет.
2) Можно также слазать в в operator "" _pin и поставить там проверку времени компиляции.
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
20.08.2019, 12:31
Цитата Сообщение от Renji Посмотреть сообщение
Еще раз, разжевано.
То есть трех раз вам недостаточно. Ладно, пойдем по четвертому.
Если сырые указатели нужны только для всякой экзотики - почему они сделаны такими простыми в доступе? Вот для всякой экзотики было бы логично усложнить работу, чтобы программист трижды подумал, так ли уж это необходимо.
Если "intPointer=(int*)doublePointer банально удобнее километрового reinterpret_cast" то зачем было вводить последний? Иначе говоря, зачем для реализации одного и того же сделано два способа? reinterpret_cast же наверное не просто так вводили.
Со struct - если бы хотели выкинуть - давно бы выкинули. Зная любовь плюсовиков к длинным запутанным выражениям, необходимость всего лишь писать public никого бы не остановила. А еще проще было ввести новое ключевое слово, обозвать struct и class устаревшими и ругаться на них warning'ами.
Ну вот не тянет это на причину сохранения подобных рудиментов в языке. Совместимость с Си - тянет.
Цитата Сообщение от Renji Посмотреть сообщение
По битам - для двух портов 8*2 все равно будет меньше чем 3*7. И сценарий "семь выводов на двух портах" явно более вероятен чем сценарий "семь выводов на семи портах".
Как я уже говорил, наиболее вероятен сценарий "семь выводов на одном порту". Он для всех проще.
Цитата Сообщение от Renji Посмотреть сообщение
Если же нужно вот прям на любой сценарий закладываться, то дует switch по usedBits. Макросы опять же не при делах.
Ну что значит не при делах, если на них получается красивее и нет необходимости полагаться на конкретную реализацию компилятора.
Я тут правильность выбрасывания if(0) отдельно тестирую, потому как мало ли, а вы предлагаете ввести десяток массивов - авось компилятор поймет, что их для красоты вводили.
Как вы понимаете, ваш вариант ведь с тем же успехом реализуем на макросах, просто на практике такое извращение обычно не нужно.
Цитата Сообщение от Renji Посмотреть сообщение
1) Поставьте заглушку std::uint8_t PORTA
Каким образом?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
20.08.2019, 14:50
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Если сырые указатели нужны только для всякой экзотики - почему они сделаны такими простыми в доступе?
Потому что кого-то надо было делать простым в доступе. std::unique_ptr не может копироваться, std::shared_ptr создает накладные расходы на поддержание счетчика ссылок. Так что на роль указателя по умолчанию остаются только сырые указатели. Хотя да, во многих случаях у них избыточный функционал.

reinterpret_cast просто идет в нагрузку к static_cast, const_cast и dynamic_cast нужным для проверки корректности каста. Такое же неудачное решение как std::vector<bool> внезапно не умеющий давать ссылки на bool.

По struct - в C++ годами хотели сделать noexcept перемещение из одного std::map в другой и все тонуло в бюрократии. Подозреваю, что с удалением struct та же история. Если бы вопрос был только в совместимости с Си, то перед сишными хедерами просто лепили бы #define struct class и все. Это куда проще чем шаманить с синтаксисом.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Как я уже говорил, наиболее вероятен сценарий "семь выводов на одном порту". Он для всех проще.
Там тем более эффективнее отправить в порт один байт из таблички, а не устанавливать каждый бит независимо.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Я тут правильность выбрасывания if(0) отдельно тестирую, потому как мало ли, а вы предлагаете ввести десяток массивов - авось компилятор поймет, что их для красоты вводили.
Это вы тестируете, а у нас Constexpr If - часть стандарта. Более того, по стандарту C++ можно целые constexpr функции использовать как константы времени компиляции. Имя в своих руках такую языковую мощь, беспокоиться о "сможет ли компилятор убрать ненужный массив" несколько глупо.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
constexpr std::size_t function()
{
    std::size_t res=0;
    for(std::size_t i=0;i<10;i++)
        res+=i;
    return res;
}
 
struct Test
{
    //а вам в Си слабо задать размер поля структуры через функцию с циклом?
    int x[function()];
};
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Каким образом?
Через отдельный хедер avrports.h. Или компилятор не предоставляет абсолютно никаких инструментов позволяющих отследить есть порт или нет?
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
20.08.2019, 15:48
Цитата Сообщение от Renji Посмотреть сообщение
Так что на роль указателя по умолчанию
Зачем вам вообще нужны "указатели по умолчанию"? Если уж начали разделять на области применения, так довели бы до конца, а то опять получается гибрид ужа с ежом. Хотя как раз это для С++ нормально.
Цитата Сообщение от Renji Посмотреть сообщение
Если бы вопрос был только в совместимости с Си, то перед сишными хедерами просто лепили бы #define struct class и все.
Так бы и сделали если бы приходилось прикручивать совместимость сбоку. Но в С++ она была от рождения, так что наличие структур и "хитрых структур" разработчикам компиляторов особо не мешает.
Цитата Сообщение от Renji Посмотреть сообщение
Там тем более эффективнее отправить в порт один байт из таблички, а не устанавливать каждый бит независимо.
Я уже понял, что у вас плохо с памятью. Ну так не ленитесь перепроверить. Код для одного порта уже был приведен.
Цитата Сообщение от Renji Посмотреть сообщение
у нас Constexpr If - часть стандарта.
И он еще удивляется, почему люди предпочитают простой и понятный Си...
Цитата Сообщение от Renji Посмотреть сообщение
Более того, по стандарту C++ можно целые constexpr функции использовать как константы времени компиляции.
Спасибо, еще один аргумент против изучения С++. То есть как обычно: идея хорошая, реализация так себе.
Цитата Сообщение от Renji Посмотреть сообщение
Через отдельный хедер avrports.h. Или компилятор не предоставляет абсолютно никаких инструментов позволяющих отследить есть порт или нет?
Без #ifndef с ходу не представляю.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
20.08.2019, 17:03
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Зачем вам вообще нужны "указатели по умолчанию"?
Для связей в графе, возможности их изменения и задания нулевого значения. Нет, мы можем вместо слова "указатели" написать "bind name to value" как в Питоне. Только это уже будет напоминать смену надписи на сарае с дровами, без замены самих дров.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Так бы и сделали если бы приходилось прикручивать совместимость сбоку. Но в С++ она была от рождения, так что наличие структур и "хитрых структур" разработчикам компиляторов особо не мешает.
В C++ и gets было, да только в C++14 сплыло. А в C++20 обещают окончательно прибить ключевое слово throw. Как раз ломать обратную совместимость языку не впервой. Причем заметьте, никто по этому поводу не говорит что C++98 и C++17 - разные языки.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Я уже понял, что у вас плохо с памятью. Ну так не ленитесь перепроверить. Код для одного порта уже был приведен.
То есть, при смене числа портов, менять код библиотеки? Я думал, мы пилим универсальный вариант, в котором только настройки менять надо.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Без #ifndef с ходу не представляю.
Если компилятор в состоянии делать отображение порт->переменная, он в состоянии и предоставить стандартный хедер с заглушками. Через что он там будет работать - не важно. Главное что хедер один и бегать по всему коду распихивая ifndef не требуется.

Добавлено через 25 минут
Цитата Сообщение от Renji Посмотреть сообщение
обещают окончательно прибить ключевое слово throw
UPD Пардон, модификатор замененный на noexcept. Броски исключений никуда не делись.
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
21.08.2019, 12:48
Цитата Сообщение от Renji Посмотреть сообщение
В C++ и gets было, да только в C++14 сплыло
То же самое в Си: было gets, потом его признали небезопасным (вроде из стандарта не убирали, но не уверен) и предлагают fgets как более универсальную и безопасную замену.
Цитата Сообщение от Renji Посмотреть сообщение
То есть, при смене числа портов, менять код библиотеки? Я думал, мы пилим универсальный вариант, в котором только настройки менять надо.
Типичная практическая задача - сегменты висят на одном порту. Задачи, где надо семисегментник повесить на несколько, я с ходу и не придумаю... разве что с ATmega8 извращаться, там функционал портам назначали как-то... нетрадиционно, но даже там это жуткая экзотика. А большинство виденных мной библиотек вообще не предполагают конфигурации.
Но по теоретическому функционалу ваш вариант весьма интересен. Осталось допилить его под реализацию конкретного avr-g++ и придумать "скрещивалку" с обычным Си-шным кодом. Сами ведь жаловались на косяки реализации avr-g++. Либо придумывать аналог на макросах, что тоже интересное развлечение.
Цитата Сообщение от Renji Посмотреть сообщение
Если компилятор в состоянии делать отображение порт->переменная
Это реализовано примерно так: #define PORTB (*(volatile uint8_t *)( 0x18 )), то есть работа непосредственно с памятью.
Нет, я вполне допускаю возможность прописать десяток
C
1
2
3
#ifndef PORTA
#define PORTA (*(volatile uint8_t *)( -1 ))
#endif
Более того, если бы я реализовывал вашу идею, я бы так и поступил. Но спрашивал я именно "без ifdef"
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
21.08.2019, 13:45
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Но по теоретическому функционалу ваш вариант весьма интересен. Осталось допилить его под реализацию конкретного avr-g++ и придумать "скрещивалку" с обычным Си-шным кодом.
Не нужно ничего придумывать, C и C++ на столько "разные" языки, что скрещивалка там давно на уровне стандарта встроена.
1) Делаете хедер в котором лежат только объявления си-стайл showNumber функций.
2) Обрамляете его extern "C" чтобы отрубить манглинг имен.
Собственно, все. И для Си, и для плюсов, gcc генерирует одни и те же .o файлы, которые спокойно между собой линкует.
C++
1
2
3
4
5
6
7
8
9
//хедер
#ifdef __cplusplus
extern "C"
{
#endif
void showNumber(unsigned value);
#ifdef __cplusplus
}
#endif
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Это реализовано примерно так: #define PORTB (*(volatile uint8_t *)( 0x18 )), то есть работа непосредственно с памятью.
То есть, есть какой-то стандартный хедер, в котором все это лежит. Ну вот в нем по идее заглушки и должны на место отсутствующих строк ставить. Если компилятор такого функционала на себя не берет, тогда да, придется делать ifdef и выносить его в dumpports.h.
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
21.08.2019, 14:35
Цитата Сообщение от Renji Посмотреть сообщение
Не нужно ничего придумывать, C и C++ на столько "разные" языки, что скрещивалка там давно на уровне стандарта встроена.
Я не имел в виду что-то настолько очевидное. Как минимум, нужно придумать способ конфигурирования. Это все решаемо, вопрос времени и желания... которого у меня на такую задачу нет. Свою библиотеку я уже давно написал и для 99% задач ее хватит. И даже если у меня появится желание адаптировать ваш вариант, скорее всего это будет перевод на макросы. Но, повторюсь, и этот вариант маловероятен.
Цитата Сообщение от Renji Посмотреть сообщение
То есть, есть какой-то стандартный хедер, в котором все это лежит.
По одному на контроллер, ведь в них могут быть разные наборы регистров. Не исключено даже что по тому адресу, где у одного контроллера лежит PORTB, у другого будет какой-нибудь UDR, причем это не от глупости разработчиков: инструкции работы с портами ввода-вывода позволяют обращаться только к 64 портам, все остальное - через память, вдвое дольше.
Цитата Сообщение от Renji Посмотреть сообщение
Ну вот в нем по идее заглушки и должны на место отсутствующих строк ставить
С чего бы? Вот выпускали они всякие AT90S*** у которых максимум PORTE был. До какой буквы им нумеровать заглушки? Нет, обычно прописывается только то, что есть в контроллере.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
21.08.2019, 15:53
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
По одному на контроллер, ведь в них могут быть разные наборы регистров.
У разных процессоров тоже могут быть разные uint_fast32_t. Тем не менее, хедер stdint.h существует в единственном экземпляре. Тип контроллера в аргументах вызова компилятора ведь указывается? Ну вот в зависимости от этих настроек хедер и должен специфичные для контроллера заглушки выдавать.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
С чего бы? Вот выпускали они всякие AT90S*** у которых максимум PORTE был. До какой буквы им нумеровать заглушки?
До Z. Во имя переносимости.
Нет у нас никакого AT90S***, есть отладочная эмуляция, работающая на настольном ПК (да, C++ позволяет перенаправить PORTA=123 на красивое окошко в Qt). И будет очень неприятно обнаружить что вылизанная в отладчике программа, попросту не компилируется в целевом контроллере. Исключительно потому что туда заглушек не доложили.
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
21.08.2019, 17:40
Цитата Сообщение от Renji Посмотреть сообщение
У разных процессоров тоже могут быть разные uint_fast32_t. Тем не менее, хедер stdint.h существует в единственном экземпляре.
Так ведь и <avr/io.h> тоже существует в единственном экземпляре, только он внутри себя инклюдит одного из io*.h (например, iom8.h для ATmega8). Разница в том, что uint_fast32_t это стандартный идентификатор, который обязан быть универсальным, а PORTA - всего лишь один из регистров, присутствующих в данном конкретном ядре. Впрочем, не подумайте что спорю: с переносимостью и здравым смыслом у Atmel все плохо: пока в камни встраивался один UART, регистр данных назывался UDR. Когда появились камни посложнее - его переименовали в UDR0, UDR1 и т.п. Но вот изменить заголовочные файлы прошлых камней им в голову не пришло. Хотя казалось бы, что сложного переименовать UDR в UDR0 и добавить линк (define) на UDR ради совместимости.
Или уже упомянутая мной работа с портами через память. Когда старой архитектуры с ее 64 портами перестало хватать, Atmel приняли вполне логичное решение вынести "лишние" регистры в память. Вот только сгруппировать их по смыслу они не догадались, в результате чего выкинули не только регистры конфигурации (их-то ладно, один раз настроил и забыл), но и регистры данных вроде того же UDR0. Вот не верю я, что так сложно было сгруппировать регистры по частоте обращения.
Цитата Сообщение от Renji Посмотреть сообщение
До Z. Во имя переносимости.
Сильно Впрочем, как раз это можно сделать и в юзерском коде, благо делается один раз, а потом кочует из проекта в проект.
Цитата Сообщение от Renji Посмотреть сообщение
Нет у нас никакого AT90S***, есть отладочная эмуляция, работающая на настольном ПК
Никто так не делает. Контроллер ведь используется не в сферическом вакууме, а в составе реальной схемы с реальной периферией. А вот симулировать это все крайне сложно. Навскидку, кроме proteus я не назову ничего. Если же хочется симуляции только внутренностей контроллера, то AVRStudio / Atmel Studio или simulavr вполне можно использовать. Но если и правда захотите потыкать контроллеры палочкой - лучше возьмите реальную отладочную плату.
Цитата Сообщение от Renji Посмотреть сообщение
И будет очень неприятно обнаружить что вылизанная в отладчике программа, попросту не компилируется в целевом контроллере. Исключительно потому что туда заглушек не доложили.
Вот эта ситуация, кстати, гораздо лучше, чем когда программа, полагающаяся на заглушки, успешно скомпилировалась, но работать не может.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
21.08.2019, 19:03
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Никто так не делает. Контроллер ведь используется не в сферическом вакууме, а в составе реальной схемы с реальной периферией. А вот симулировать это все крайне сложно.
И как эта реальная периферия сочетается с пошаговой отладкой?
Понятно, что эмуляция будет крайне грубой, на уровне "просвистеть заранее подготовленные данные". Но совсем от нее отказываться достаточно странно. Отлаживать программу лишь в режиме "контроллер завис, перечитывай код пытаясь понять почему" тоже удовольствие так себе.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Вот эта ситуация, кстати, гораздо лучше, чем когда программа, полагающаяся на заглушки, успешно скомпилировалась, но работать не может.
Скомпилировалась и прошла какие-то тесты. Это внушает больше доверия чем программа без заглушек, которая пока что только скомпилировалась.
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
22.08.2019, 13:37
Цитата Сообщение от Renji Посмотреть сообщение
И как эта реальная периферия сочетается с пошаговой отладкой?
Обычно плохо. Именно поэтому отладчики, даже JTAG, далеко не так популярны, как в "компьютерном" программировании.
Цитата Сообщение от Renji Посмотреть сообщение
Понятно, что эмуляция будет крайне грубой, на уровне "просвистеть заранее подготовленные данные".
Ничто ж не мешает ставить заглушки на более высокоуровневые функции, чем работа с портами и отлаживать сам алгоритм. И то бывают ситуации, завязанные на подсчет тактов - тут кроме "честной" симуляции или железа вариантов и нет. Или особенности работы с прерываниями.
Цитата Сообщение от Renji Посмотреть сообщение
Скомпилировалась и прошла какие-то тесты. Это внушает больше доверия чем программа без заглушек, которая пока что только скомпилировалась.
Опять подменяете понятия. Потому что варианты - "скомпилировалась, полагаясь на заглушки" и "не скомпилировалась за неимением заглушек". Так вот, второй вариант лучше.
Цитата Сообщение от Renji Посмотреть сообщение
Отлаживать программу лишь в режиме "контроллер завис, перечитывай код пытаясь понять почему" тоже удовольствие так себе.
А что, у вас кто-то отбирает отладочный вывод по UART'у?

Добавлено через 3 часа 19 минут
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
И даже если у меня появится желание адаптировать ваш вариант, скорее всего это будет перевод на макросы. Но, повторюсь, и этот вариант маловероятен.
Ан нет! Задача оказалась слишком безумной чтобы ее проигнорировать. Реализация на макросах!
7seg_2.h
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#ifndef __7SEG_2_H__
#define __7SEG_2_H__
 
#include <inttypes.h>
#include <avr/pgmspace.h>
#include "pinmacro.h"
 
#define __PMSK(templ, port, bit) ( (LET_##templ == LET_##port) << bit )
#define _PMSK(templ, port, bit) __PMSK(templ, port, bit)
#define PMSK(seg) _PMSK(INC_PORT, seg)
 
#if SEG_ACTIVE
#define SET_POL(x) ((x))
#else
#define SET_POL(x) ((uint8_t)(~(x)))
#endif
 
#define LET_A 1
#define LET_B 2
#define LET_C 3
#define LET_D 4
#define LET_E 5
#define LET_F 6
#define LET_G 7
#define LET_H 8
#define LET_I 9
#define LET_J 10
#define LET_K 11
#define LET_L 12
#define LET_M 13
#define LET_N 14
#define LET_O 15
#define LET_P 16
#define LET_Q 17
#define LET_R 18
#define LET_S 19
#define LET_T 20
#define LET_U 21
#define LET_V 22
#define LET_W 23
#define LET_X 24
#define LET_Y 25
#define LET_Z 26
 
 
void show_init(){
  DDR_1(SEG_A);
  DDR_1(SEG_B);
  DDR_1(SEG_C);
  DDR_1(SEG_D);
  DDR_1(SEG_E);
  DDR_1(SEG_F);
  DDR_1(SEG_G);
}
  
void show_num( uint8_t num ){
#define INC_PORT A
#include "7seg_2.h"
#define INC_PORT B
#include "7seg_2.h"
#define INC_PORT C
#include "7seg_2.h"
#define INC_PORT D
#include "7seg_2.h"
#define INC_PORT E
#include "7seg_2.h"
#define INC_PORT F
#include "7seg_2.h"
#define INC_PORT G
#include "7seg_2.h"
#define INC_PORT H
#include "7seg_2.h"
#define INC_PORT I
#include "7seg_2.h"
#define INC_PORT J
#include "7seg_2.h"
#define INC_PORT K
#include "7seg_2.h"
#define INC_PORT L
#include "7seg_2.h"
#define INC_PORT M
#include "7seg_2.h"
#define INC_PORT N
#include "7seg_2.h"
#define INC_PORT O
#include "7seg_2.h"
#define INC_PORT P
#include "7seg_2.h"
#define INC_PORT Q
#include "7seg_2.h"
#define INC_PORT R
#include "7seg_2.h"
#define INC_PORT S
#include "7seg_2.h"
#define INC_PORT T
#include "7seg_2.h"
#define INC_PORT U
#include "7seg_2.h"
#define INC_PORT V
#include "7seg_2.h"
#define INC_PORT W
#include "7seg_2.h"
#define INC_PORT X
#include "7seg_2.h"
#define INC_PORT Y
#include "7seg_2.h"
#define INC_PORT Z
#include "7seg_2.h"
}
 
 
#undef LET_A
#undef LET_B
#undef LET_C
#undef LET_D
#undef LET_E
#undef LET_F
#undef LET_G
#undef LET_H
#undef LET_I
#undef LET_J
#undef LET_K
#undef LET_L
#undef LET_M
#undef LET_N
#undef LET_O
#undef LET_P
#undef LET_Q
#undef LET_R
#undef LET_S
#undef LET_T
#undef LET_U
#undef LET_V
#undef LET_W
#undef LET_X
#undef LET_Y
#undef LET_Z
 
#undef __PMSK
#undef _PMSK
#undef PMSK
#undef SET_POL
 
 
 
#else
 
 
 
#define MASK (\
  PMSK(SEG_A) | PMSK(SEG_B) | PMSK(SEG_C) | PMSK(SEG_D) | \
  PMSK(SEG_E) | PMSK(SEG_F) | PMSK(SEG_G) )
 
#if (MASK != 0)
{
  static PROGMEM const uint8_t arr[] = {
    SET_POL( PMSK(SEG_A) | PMSK(SEG_B) | PMSK(SEG_C) | PMSK(SEG_D) | PMSK(SEG_E) | PMSK(SEG_F) ), //0
    SET_POL( PMSK(SEG_B) | PMSK(SEG_C) ), //1
    SET_POL( PMSK(SEG_A) | PMSK(SEG_B) | PMSK(SEG_D) | PMSK(SEG_E) | PMSK(SEG_G) ), //2
    SET_POL( PMSK(SEG_A) | PMSK(SEG_B) | PMSK(SEG_C) | PMSK(SEG_D) | PMSK(SEG_G) ), //3
    SET_POL( PMSK(SEG_B) | PMSK(SEG_C) | PMSK(SEG_F) | PMSK(SEG_G) ), //4
    SET_POL( PMSK(SEG_A) | PMSK(SEG_C) | PMSK(SEG_D) | PMSK(SEG_F) | PMSK(SEG_G) ), //5
    SET_POL( PMSK(SEG_A) | PMSK(SEG_C) | PMSK(SEG_D) | PMSK(SEG_E) | PMSK(SEG_F) | PMSK(SEG_G) ), //6
    SET_POL( PMSK(SEG_A) | PMSK(SEG_B) | PMSK(SEG_C) ), //7
    SET_POL( PMSK(SEG_A) | PMSK(SEG_B) | PMSK(SEG_C) | PMSK(SEG_D) | PMSK(SEG_E) | PMSK(SEG_F) | PMSK(SEG_G) ), //8
    SET_POL( PMSK(SEG_A) | PMSK(SEG_B) | PMSK(SEG_C) | PMSK(SEG_D) | PMSK(SEG_F) | PMSK(SEG_G) ), //9
  };
  
  uint8_t port = PORTx( INC_PORT );
#if SEG_ACTIVE
  port &=~ MASK;
  port |= pgm_read_byte(&arr[num]);
#else
  port |= MASK;
  port &= pgm_read_byte(&arr[num]);
#endif
  PORTx( INC_PORT ) = port;
}
#endif
#undef MASK
 
#undef INC_PORT
#endif
Два самых больших выноса мозга - километровый копипаст заглушек и инклюд файла внутрь самого себя.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
22.08.2019, 15:33
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Ничто ж не мешает ставить заглушки на более высокоуровневые функции, чем работа с портами и отлаживать сам алгоритм. И то бывают ситуации, завязанные на подсчет тактов - тут кроме "честной" симуляции или железа вариантов и нет. Или особенности работы с прерываниями.
Чтобы ставить заглушки на функции, их сначала надо изолировать от работы с портами. Я как-то не уверен что это всегда возможно. Особенно, если задачей функции является отправить данные в такой-то порт, по сякому протоколу. Да и винегрет из PORTA|=1<<3 и PORTA=3 лучше покрыть тестами во избежание удара граблями по лбу.
Прерывая вполне воспроизводятся на уровне "заморозить основной тред, выполнить обработчик прерывания, разморозить тред". Хотя и не средствами STL.

Профилирование да, надо гонять на реальном железе. Но это же не повод вообще от предварительной отладки отказываться.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Опять подменяете понятия. Потому что варианты - "скомпилировалась, полагаясь на заглушки" и "не скомпилировалась за неимением заглушек". Так вот, второй вариант лучше.
Перечитайте исходный пост, там сразу было написано "вылизанная в отладчике программа".
Без заглушек ни отладчик не запустился, ни авто-тесты не запустились. Известно только что код компилируется или не компилируется, а дальше надо за программатором бежать.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
А что, у вас кто-то отбирает отладочный вывод по UART'у?
Чтобы ловить ошибки по отладочному выводу, надо хотя бы бэктрейс сделать. Причем, так как мы не знаем место ошибки, этот бэктрейс придется пихать в каждую дырку. Причем, все это ручками. Достаточно сомнительное решение по сравнению с "хоть как то запустить под отладчиком".
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Два самых больших выноса мозга - километровый копипаст заглушек и инклюд файла внутрь самого себя.
Вот именно что вынос мозга. Навелосипедить шаблоны на макросах можно, но вот читаемость у них будет весьма сомнительна.
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
22.08.2019, 16:06
Цитата Сообщение от Renji Посмотреть сообщение
Чтобы ставить заглушки на функции, их сначала надо изолировать от работы с портами.
Это уже вопрос конкретной задачи. В каких-то случаях имеет смысл использовать отладчик или эмулятор, в других - только на железе.
Цитата Сообщение от Renji Посмотреть сообщение
Прерывая вполне воспроизводятся на уровне "заморозить основной тред, выполнить обработчик прерывания, разморозить тред". Хотя и не средствами STL.
Совершенно точно - нет. Вы никогда не попадете точно в такты, а для обработки регистров ядра придется опять же писать симулятор. И прерывания это не просто прерывания - это тот же ввод данных, счет времени и т.п.
Цитата Сообщение от Renji Посмотреть сообщение
бэктрейс придется пихать в каждую дырку. Причем, все это ручками. Достаточно сомнительное решение по сравнению с "хоть как то запустить под отладчиком".
Особенно когда проблема в отладчике не воспроизводится. Скажем, периферия сгорела, или юзер лапками натыкал. Нет, когда все завязано на железо, пытаться симулировать только порты - безнадежно.
Цитата Сообщение от Renji Посмотреть сообщение
Вот именно что вынос мозга. Навелосипедить шаблоны на макросах можно, но вот читаемость у них будет весьма сомнительна.
Но все же лучше, чем ваш вариант на шаблонах и constexpr'ах. Развернуть ваш вариант на все порты - так он еще длиннее будет.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
22.08.2019, 18:04
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Совершенно точно - нет. Вы никогда не попадете точно в такты, а для обработки регистров ядра придется опять же писать симулятор. И прерывания это не просто прерывания - это тот же ввод данных, счет времени и т.п.
Я не знаю зачем вам нужно попадать в такты, но для этого вам придется как минимум отказаться от Си. Потому что Си-компилятор никому не обещал что всегда будет компилировать один и тот же код, в один и тот же ассемблерный листинг. Если речь про задержки вида "цикл с тысячей nop", ну так выносятся в отдельную функцию, которая заменяется заглушкой.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Особенно когда проблема в отладчике не воспроизводится. Скажем, периферия сгорела, или юзер лапками натыкал. Нет, когда все завязано на железо, пытаться симулировать только порты - безнадежно.
С чего вдруг не воспроизводится? Просто к тесту "эмуляция корректного ввода", добавляется тест "эмуляция белого шума на входе" и тест "гробовая тишина на входе".
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Но все же лучше, чем ваш вариант на шаблонах и constexpr'ах. Развернуть ваш вариант на все порты - так он еще длиннее будет.
У меня длинного только простыня if(usedBits.getByte(0)). Развернуть его на все порты и будет еще плюс 44 строки. До ваших 180 все равно и близко не дотянет. Можно в принципе без простыни, но чуть сложнее.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template<unsigned portNumber,typename PortType,typename...Args>
void showNumber(unsigned number,PortType&port,Args&...args)
{
    if constexpr(usedBits.getByte(portNumber))
        port=(port&~usedBits.getByte(portNumber))|getMask<portNumber>(number);
    if constexpr(portNumber<3)
        showNumber<portNumber+1,Args...>(number,args...);
}
 
void showNumber(unsigned number)
{
    showNumber<0>(number,PORTA,PORTB,PORTC,PORTD);
}
0
 Аватар для COKPOWEHEU
4150 / 2728 / 433
Регистрация: 09.09.2017
Сообщений: 12,099
23.08.2019, 10:38
Цитата Сообщение от Renji Посмотреть сообщение
С чего вдруг не воспроизводится?
Потому что вы предлагаете симулировать только один слой, добавляя заглушки, которые ведут себя совершенно не так, как реальный код. Впрочем, такой подход тоже имеет право на жизнь, о чем я уже писал: "поставить заглушки на более высокоуровневые функции и отлаживать алгоритм".
Цитата Сообщение от Renji Посмотреть сообщение
У меня длинного только простыня if(usedBits.getByte(0)).
Проблема не в самой простыне: копипаст глазами просматривается мгновенно. Проблема что вам приходится менять маску и имя порта: if(usedPorts&0xFF) PORTA=getNumberMask<0>(number); плюс заглушки на порты. Добавляем #ifdef+#endif получаем 4 строчки на букву - вот уже 104 строчки, причем менять приходится разные элементы, значит выше риск опечатки.
Цитата Сообщение от Renji Посмотреть сообщение
До ваших 180 все
Если поубирать часть #undef'ов, настройки и прочие "украшательства", которых в вашем коде не предусмотрено, получится 120 строчек, из которых 75 - простой копипаст и не нуждается в анализе. То есть реального кода там около 45 строчек. Обратите внимание, что там нет никаких шаблонов и прочего трудноанализируемого синтаксиса.
Цитата Сообщение от Renji Посмотреть сообщение
Можно в принципе без простыни, но чуть сложнее.
Приведите, пожалуйста, полный код. Те куски, что вы выкладывали раньше, собрать не получается.:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <avr/io.h>
#include <stdlib.h>
 
class bitset{
public:
    static constexpr auto size = 32;
 
    constexpr bitset(){}
    constexpr bitset(unsigned shift,unsigned port){ data[port] = (1<<shift);}
    constexpr bitset operator | (const bitset&value) const {
        bitset res;
        for(unsigned pos=0; pos<size; ++pos)
            res.data[pos] = data[pos] | value.data[pos];
        return res;
    }
    constexpr uint8_t getByte(size_t pos) const { return data[pos]; }
private:
    uint8_t data[size] = {0};
};
 
constexpr bitset operator "" _pin(const char*str, size_t){
    return bitset (str[1]-'0',str[0]-'A');
}
 
constexpr bitset segmentA="A3"_pin;
constexpr bitset segmentB="D1"_pin;
constexpr bitset usedBits=segmentA|segmentB;
 
template<unsigned port>
uint8_t getMask(unsigned number){
    static const uint8_t data[10]={
        (segmentA|segmentB).getByte(port),
        segmentA.getByte(port),
        segmentB.getByte(port),
        segmentA.getByte(port),
        segmentA.getByte(port),
        segmentA.getByte(port),
        segmentA.getByte(port),
        segmentA.getByte(port),
        segmentA.getByte(port),
        segmentA.getByte(port)
    };
    return data[number];
}
 
template<unsigned portNumber,typename PortType,typename...Args>
void showNumber(unsigned number,PortType&port,Args&...args){
    if constexpr(usedBits.getByte(portNumber))
        port=(port&~usedBits.getByte(portNumber))|getMask<portNumber>(number);
    if constexpr(portNumber<3)
        showNumber<portNumber+1,Args...>(number,args...);
}
 
void showNumber(unsigned number){
    /*showNumber<0>(number,
                  PORTA, PORTB, PORTC, PORTD, PORTE, PORTF, PORTG, PORTH,
                  PORTI, PORTJ, PORTK, PORTL, PORTM, PORTN, PORTO, PORTP,
                  PORTQ, PORTR, PORTS, PORTT, PORTU, PORTV, PORTW, PORTX,
                  PORTY, PORTZ
                 ); */
    showNumber<0>(number, PORTB, PORTB, PORTC, PORTD);
}
 
int main(){
  showNumber(0);
}
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ avr-g++ -std=c++17 main.c -mmcu=atmega8 -Os -DF_CPU=1000000 -o a.elf -Wall -Wextra -Wpedantic
main.c: In function ‘void showNumber(unsigned int, PortType&, Args& ...)’:
main.c:48:8: error: expected ‘(’ before ‘constexpr’
     if constexpr(usedBits.getByte(portNumber))
        ^
main.c:50:8: error: expected ‘(’ before ‘constexpr’
     if constexpr(portNumber<3)
        ^
main.c: In instantiation of ‘void showNumber(unsigned int, PortType&, Args& ...) [with unsigned int portNumber = 0u; PortType = volatile unsigned char; Args = {volatile unsigned char, volatile unsigned char, volatile unsigned char}]’:
main.c:61:53:   required from here
main.c:47:26: warning: unused parameter ‘number’ [-Wunused-parameter]
 void showNumber(unsigned number,PortType&port,Args&...args){
                          ^
main.c:47:42: warning: unused parameter ‘port’ [-Wunused-parameter]
 void showNumber(unsigned number,PortType&port,Args&...args){
                                          ^
main.c:47:55: warning: unused parameter ‘args#0’ [-Wunused-parameter]
 void showNumber(unsigned number,PortType&port,Args&...args){
                                                       ^
main.c:47:55: warning: unused parameter ‘args#1’ [-Wunused-parameter]
main.c:47:55: warning: unused parameter ‘args#2’ [-Wunused-parameter]
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.08.2019, 10:38

std::vector<int> Что это за тип данных?
std::vector&lt;int&gt; indexes_1, indexes_2; // Used for homography Что это за тип данных?

Что значит (для сущности «вершина» создать новый тип данных)?
Задание такое: Написать функцию для вычисления площади треугольника на плоскости, заданного координатами вершин. (для сущности «вершина»...

Восьмибитный тип переменной (что за тип, но не BYTE и не CHAR?
Вроде давно занимаюсь программированием на С++, но встала проблема... Есть некий массив переменных имеющих 8 битный размер... без знака...

Объясните, что это: "static const uint32_t collisionCategory = 0x1 << 0"?
Встретил в одном туториале по SpriteKit следующую строчку static const uint32_t projectileCategory = 0x1 &lt;&lt; 0; Подскажите...

Как сделать тип данных или уже есть такой тип данных который состоит из всех печатыемых символов?
Как сделать тип данных или уже есть такой тип данных который состоит из всех печатыемых символов? Если есть то как он называется ?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
160
Ответ Создать тему
Новые блоги и статьи
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru