Ответ вы знаете. Другого у меня для вас нет.
Теперь немного о сказках насчет крайне затратного приведения типов. Есть функция:
Код: Выделить всё
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
Число и тип параметров не я придумал, а небезызвестная
Bosch Sensortec. Этот пример я здесь привожу только потому, что именно сегодня мне взбрело в голову поковырять BME280, а в коде от BOSH оно и всплыло. Смотрим на функцию и видим параметр
len, который объявлен, как беззнаковое 16-битное целое. Сначала мне показалось (и небезосновательно), что 65535 значений это сильно "дофига" для чтения регистров BME280, которых всего 45 штук и разрядность у них -- ровно один байт у каждого. Пошерстил исходники -- так и есть -- все передаваемые значения -- исключительно 8-битные константы. Уже непонятно, кто там в этой BOSCH такое пишет, но да не об этом сейчас.
Попробовал менять тип последнего параметра на так любимый здесь многими
uint8_t и столь же нелюбимый
int. Вот какие варианты кода функции в итоге сварил компилятор (µVision V5.24.2.0, C Compiler: Armcc.exe V5.06 update 5 build 528) в области использования переменной
len:
Код: Выделить всё
=== [ uint16_t ] ===========
151: while (len > 0) {
0x00000310 E035 B 0x0000037E
152: if (--len == 0) {
0x00000312 1E58 SUBS r0,r3,#1
0x00000314 B280 UXTH r0,r0
0x00000316 1E03 SUBS r3,r0,#0
0x00000318 D103 BNE 0x00000322
=== [ uint8_t ] ============
151: while (len > 0) {
0x00000310 E035 B 0x0000037E
152: if (--len == 0) {
0x00000312 1E58 SUBS r0,r3,#1
0x00000314 B2C0 UXTB r0,r0
0x00000316 1E03 SUBS r3,r0,#0
0x00000318 D103 BNE 0x00000322
=== [ int ] ================
151: while (len > 0) {
0x00000310 E034 B 0x0000037C
152: if (--len == 0) {
0x00000312 1E58 SUBS r0,r3,#1
0x00000314 1E03 SUBS r3,r0,#0
0x00000316 D103 BNE 0x00000320
Код работает во всех случаях, но есть нюансы. В листингах выше можно воочию наблюдать, что россказни будто тип переменной обязательно должен соответствовать разрядности использующихся данных, оказываются на поверку полной туфтой. Компилятор добавляет разрядность до наиболее комфортной процессору, т.е. до 32-х бит.
uint8_t он расширяет командой
UXTB, а
uint16_t командой
UXTH именно до 32-х бит. Зато 32-битный
int используется без дополнительных преобразований. На снайпетах выше приводятся все случаи использования переменной
len внутри функции и какие-либо "скрытые" или "неучтенные" причины приведения переменной к 32-м битам отсутствуют. Вот и сказочкам конец.
PS. Нашел еще один маленький перл в бошевской библиотеке. Кто-нибудь может перевести?:
Мне по собственному скудомыслию кажется, что писавший сие и в школу-то никогда не ходил. Только этим я могу объяснить вложенные скобки. Внешние так и вовсе не могу объяснить. Помогите!
