juvf 17 10 декабря, 2018 Опубликовано 10 декабря, 2018 · Жалоба 17 минут назад, jcxz сказал: Спасибо. Буду иметь в виду. в с11++ много вкусного.... тот же For-цикл по коллекции. вам такому специалисту как вы, должно быть стыдно не знать на пороге 2019 про тип auto. Может пора начать учить с11++ ознакомиться с С++11, хотя бы на вики. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 10 декабря, 2018 Опубликовано 10 декабря, 2018 · Жалоба Господа, давайте без перехода на личности :( А для решения проблемы разрядности целочисленных типов люди собрались и ввели в стандарт stdint.h Кто этим не пользуется, тот ССЗБ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 10 декабря, 2018 Опубликовано 10 декабря, 2018 · Жалоба 27 минут назад, juvf сказал: в с11++ много вкусного.... тот же For-цикл по коллекции. вам такому специалисту как вы, должно быть стыдно не знать на пороге 2019 про тип auto. Может пора начать учить с11++ ознакомиться с С++11, хотя бы на вики. Я вроде вообще к вам не обращался. Своё мнение о вас я уже составил. И о вашем уровне "компетенции". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
razrab83 21 10 декабря, 2018 Опубликовано 10 декабря, 2018 · Жалоба 8 часов назад, jcxz сказал: В указанных случаях, например на ARM (и на других архитектурах) следует использовать int (или unsigned int). всякие uint8_t будут приводить к неоптимальному коду. каким образом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 10 декабря, 2018 Опубликовано 10 декабря, 2018 · Жалоба 7 минут назад, razrab83 сказал: каким образом? Дополнительными командами приведения типа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 10 декабря, 2018 Опубликовано 10 декабря, 2018 · Жалоба Как бы очевидно, что использование типов данных по разрядности совпадающих с разрядностью процессора ведёт к исключению накладных расходов на приведение типов. Для 8-биток это (u)int8_t, так как int будет 16-битный. С другой стороны, в программе лучше применять типы данных соответствующие описываемым ими сущностям. Так и ошибок будет меньше, и переносимость кода выше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
razrab83 21 10 декабря, 2018 Опубликовано 10 декабря, 2018 (изменено) · Жалоба 1 час назад, jcxz сказал: Дополнительными командами приведения типа. что, где и к чему должно быть приведено? собрал for( int/uint8_t i = 0; i< 10; i++) с int и c uint8_t. На разных архитектурах (8 и 32 бита), разными компиляторами для каждой архитектуры, без оптимизации, с оптимизацией..... глянул дизасм.... пошагал.... код что с int, что с uint8_t получился одинаковый.... не то что по размеру или по скорости... получился одинаковый в точности до каждой машинной команды. Изменено 10 декабря, 2018 пользователем razrab83 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 10 декабря, 2018 Опубликовано 10 декабря, 2018 · Жалоба Проще всего эти команды обнаружить передавая в функцию и возвращая из функции на ARM int8_t и int32_t в разных сочетаниях. Вот смотри, простейший пример. Всё чисто. // int32_t foo(int32_t x) // { // return x*2; LSLS R0,R0,#+1 BX LR ;; return // } // volatile uint32_t a=10; MOVS R0,#+10 STR R0,[SP, #+0] // volatile uint32_t b = foo(a); LDR R1,[SP, #+0] LSLS R1,R1,#+1 STR R1,[SP, #+0] А теперь поменяем возвращаемый тип. // int8_t foo(int32_t x) // { // return x*2; LSLS R0,R0,#+25 ASRS R0,R0,#+24 BX LR ;; return // } // volatile uint32_t a=10; MOVS R0,#+10 STR R0,[SP, #+0] // volatile uint32_t b = foo(a); LDR R1,[SP, #+0] LSLS R0,R1,#+1 SXTB R0,R0 STR R0,[SP, #+0] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 10 декабря, 2018 Опубликовано 10 декабря, 2018 · Жалоба 1 час назад, razrab83 сказал: что, где и к чему должно быть приведено? for (uint8_t i = 0; i < 10; i++) {...} 10 - по дефолту тип int, i - uint8_t (меньшего размера). Соответственно один операнд (меньшего размера) будет приведён к типу другого (большего размера и другой разрядности). См. описание языка си, раздел правил приведения типов операндов внутри выражений. Цитата собрал for( int/uint8_t i = 0; i< 10; i++) с int и c uint8_t. На разных архитектурах (8 и 32 бита), разными компиляторами для каждой архитектуры, без оптимизации, с оптимизацией..... глянул дизасм.... пошагал.... код что с int, что с uint8_t получился одинаковый.... не то что по размеру или по скорости... получился одинаковый в точности до каждой машинной команды. Значит - данный компилятор в данном конкретном случае (с данными ключами) данный конкретный пример уже оптимизирует, приводя сразу типы операндов. Вот что сказал IAR_7.80.4 for ARM (оптимизация - LOW): Спойлер 428 void zf(void const *data, uint) 429 { 430 u8 const *p = (u8 const *)data; 431 for (u8 i = 0; i < 10; i++) *(u8 *)&CRC.DR = *p++; \ _Z2zfPKvj: (+1) \ 00000000 0x2100 MOVS R1,#+0 \ 00000002 0xE004 B.N ??zf_0 \ ??zf_1: (+1) \ 00000004 0x7802 LDRB R2,[R0, #+0] \ 00000006 0x.... LDR.N R3,??DataTable14_39 ;; 0x40023000 \ 00000008 0x701A STRB R2,[R3, #+0] \ 0000000A 0x1C40 ADDS R0,R0,#+1 \ 0000000C 0x1C49 ADDS R1,R1,#+1 \ ??zf_0: (+1) \ 0000000E 0xB2C9 UXTB R1,R1 ;; ZeroExt R1,R1,#+24,#+24 \ 00000010 0x290A CMP R1,#+10 \ 00000012 0xDBF7 BLT.N ??zf_1 432 } \ 00000014 0x4770 BX LR ;; return Команда UXTB - это как раз и есть команда беззнакового расширения. Без которой можно обойтись, применив uint i. Как справедливо заметил VladislavS приведения типа чаще можно увидеть при передаче аргументов функций не основной разрядности (разрядность != разрядности регистров CPU). Возьмите любой код, насыщенный всякими uint8_t/uint16_t в аргументах и локальных переменных функций, скомпилируйте его на 32-битной архитектуре, и увидите кучу UXTB/UXTH/SXTB/SXTH. Например этим сильно грешат исходники uCOS-II - всяких INT8U/INT16U в аргументах там полно. То же самое касается и других архитектур (STM8 - в том числе), когда передаются аргументы в функцию или используются как локальные, переменные не основной разрядности. В STM8 предпочтительно использовать 8бит, если не лезет - 16бит, и только потом уже - 32бита. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 11 декабря, 2018 Опубликовано 11 декабря, 2018 · Жалоба 9 часов назад, VladislavS сказал: Вот смотри, простейший пример. Всё чисто. int8_t foo(int32_t x) { return x*2; } Где же тут чисто? У вас foo возвращает int8_t, а вы в ретурн суёте int32_t. Тут неявное преобразование на уровне си/с++ return (int8_t)(x*2); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 11 декабря, 2018 Опубликовано 11 декабря, 2018 · Жалоба Вы хотели посмотреть команды приведения типов - я вам их показал. Они будут неизбежно появляться там где разрядность данных не совпадает с разрядностью процессора. Вот функция без приведения типов // int8_t foo(int8_t x) // { // return x-20; SUBS R0,R0,#+20 SXTB R0,R0 BX LR ;; return // } Если бы разрядность процессора совпадала с данными, то всё было бы проще // int32_t foo(int32_t x) // { // return x-20; SUBS R0,R0,#+20 BX LR ;; return // } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 12 декабря, 2018 Опубликовано 12 декабря, 2018 · Жалоба uint_fast8_t // uint_fast8_t foo(uint_fast8_t x) // { // return x-20; SUBS R0,R0,#+20 BX LR ;; return // } ps акказываица, не я один до такого дожил. вот что думают об этом в Micrium руководстве по портированию uc/os Цитата Поскольку различные микропроцессоры имеют различную длину слова, портация μC/OS-II включает ряд определений типов для гарантии переносимости. В особенности, коды μC/OS-II никогда не используют типы данных С short, int и long, потому что они не переносимые. Вместо этого, определены целочисленные типы данных, которые и переносимы, и интуитивно понятны Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 12 декабря, 2018 Опубликовано 12 декабря, 2018 · Жалоба Да ну на. Даже боюсь сравнить результат int8_t foo(int8_t x) { if((x+127)>0) return 1; else return 0; } или int_fast8_t foo(int_fast8_t x) { if((x+127)>0) return 1; else return 0; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
razrab83 21 12 декабря, 2018 Опубликовано 12 декабря, 2018 · Жалоба 90 int_fast8_t foo(int_fast8_t x) foo: 08004cb4: foo: MOVS R1, R0 92 if((x+127)>0) return 1; else return 0; 08004cb6: ADDS.W R0, R1, #127 ; 0x7f 08004cba: CMP R0, #1 08004cbc: BLT.N 0x8004cc2 08004cbe: MOVS R0, #1 08004cc0: B.N 0x8004cc4 08004cc2: MOVS R0, #0 08004cc4: BX LR 90 int foo(int x) foo: 08004cb4: foo: MOVS R1, R0 92 if((x+127)>0) return 1; else return 0; 08004cb6: ADDS.W R0, R1, #127 ; 0x7f 08004cba: CMP R0, #1 08004cbc: BLT.N 0x8004cc2 08004cbe: MOVS R0, #1 08004cc0: B.N 0x8004cc4 08004cc2: MOVS R0, #0 08004cc4: BX LR ARM, IAR, без оптимизации. Я тоже считаю, что лучше применять типы данных соответствующие описываемым ими сущностям. Код должен быть понятный и наглядный (а часто ещё и легко переносимый). Что касательно избыточности - современные компиляторы хорошо умеют справляются с "чужой" разрядностью. всякие оптимизаторы, int_fastN_t, intN_t, int_leastN_t ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 12 декабря, 2018 Опубликовано 12 декабря, 2018 · Жалоба 1 час назад, razrab83 сказал: ARM, IAR, без оптимизации. Как и где определён этот самый uint_fast8_t? Мой IAR_7.80.4 его не знает. И в uCOS-II его тоже нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться