-
- Практически - да, но есть тонкости: uint32_t не одно и то же что и
unsigned long int : в памяти одинаковы, размер одинаков, а типы -
разные. Dingo(314 знак., 18.09.2020 10:56)
- И как вы с этим живёте?! И как я буду с этим жить? - teap0t(18.09.2020 10:59)
- typeof -- это плюсы, даже не отвлекайтесь на это. Мы и без них
запутаемся. - SciFi(18.09.2020 11:10)
- Увы, typeof есть только у GCC, его нет в стандартах С или С++. - ЫЫyкпy(18.09.2020 13:08)
- Ну наконец-то хоть что-то обнадёживающее! - teap0t(18.09.2020 11:11)
- Особенно, когда переносишь с Builder в RAD Studio и программа перестает работать. - BlackMorda(18.09.2020 12:05)
- typeof -- это плюсы, даже не отвлекайтесь на это. Мы и без них
запутаемся. - SciFi(18.09.2020 11:10)
- И как вы с этим живёте?! И как я буду с этим жить? - teap0t(18.09.2020 10:59)
- Для 32-разрядной константы на 32-разрядном ядре. Иначе лучше писать
в скобках с приведением типа. - POV_(18.09.2020 10:45, )
- Ядро 32 разряда - STM32. Короче, правильно как в оригинале teap0t(92 знак., 18.09.2020 10:52)
- Какой смысл имеет типизация константы не по месту ее применения,
непонятно. А все непонятное неправильно. - VLLV(18.09.2020 10:56)
- Вопрос возник из-за такого кода (сразу предлагаю отвлечься от
оскорбительного национализма в определениях): teap0t(911 знак., 18.09.2020 11:45 - 16:55)
- Это говнокод. Не нужны там никакие приведения типа. Ну и регистр
FLASH->SR в хедерах объявлен 32-разрядным, поэтому
"допускающего по документации 8-, 16- и 32-разрядное обращение"
неведомо компилятору. - SciFi(18.09.2020 11:49)
- На SPI stm32f0 вляпался, что 16-битная запись выводит 2 байта, а 8
битная - один. Это описано в RM, но не очевидно. Andreas(118 знак., 18.09.2020 12:14)
- Разумеется, нужно приведение типа, если вы хотите обратиться к
части регистра, например отдельно к старшей и младшей половине
BSRR. Но если вы пишете в регистр целиком, это лишнее. А
(uint32_t)0 - совсем лишнее. И это лишнее не безобидно: компилятору
насрать, а человека, который взялся это читать, шум отвлекает. - йцyкeн(18.09.2020 12:27)
- Я, собственно, именно из-за пестроты кода полез со всем этим
разбираться. В тексте постоянно встречаются директивы указания
разрядности. Причём мне непонятно, зачем надо заводить 16-разрядную
переменную и постоянно указывать разрядность операций. Можно же
взять 32-разрядную, работать с ней и только перед самой записью в
регистр указать разрядность. Но я же должен убедиться, что всё
правильно понимаю? Поэтому задаю вопросы. Приятно осознавать, что
таки да, правильно понимаю. - teap0t(18.09.2020 15:22)
- Указание разрядности необходимо в целочисленной арифметике. - VLLV(18.09.2020 15:32)
- Всё так, только "перед самой записью в регистр указать разрядность"
не надо, это лишнее. - SciFi(18.09.2020 15:27)
- Раскройте мысль. Я, конечно, понимаю, что в 16-разрядный регистр 32
разряда не поместятся, и записаны будут только младшие биты.
Собственно, для того и берётся максимальный размер переменной,
чтобы приведение шло исключительно с обрезанием старших разрядов.
Но для компилятора это разве не имеет значения? Может будет
неправильная ассемблерная команда передачи использоваться (пример
условный)? - teap0t(18.09.2020 17:00)
- На всякий случай скажу банальность: побитные логические операции на
то и побитные, что разряды друг на друга не влияют. Сложение,
вычитание и умножение порождают переносы, при которых младшие биты
влияют на старшие, но никогда наоборот. Только деление и сдвиг
вправо приводят к влиянию старших разрядов на младшие. Поэтому,
если выражение не содержит деления и сдвига вправо, вычисления с
"лишней" разрядностью в соответствии с правилами integer promotion
не влияют на результат. йцyкeн(150 знак., 18.09.2020 18:33)
- Мне хочется минимизировать неоднозначность операций и снизить
вмешательство компилятора до минимально необходимого. (Пока не
освоился со всем этим). - teap0t(18.09.2020 18:42)
- Язык Си очень близок к
железукремнию, вмешательство компилятора минимально. Если писать на ассемблере, операции всё равно будут производиться над 32-битными регистрам, операции над половинками и четвертинками отсутствуют за исключением очень специальных команд. По крайней мере в Cortex-M3; у M4 и M7 есть SIMD инструкции. - йцyкeн(18.09.2020 19:43)- Ну да, вмешательство компилятора минимально. А потом он всё
оптимизирует, и погромист недоумевает "где мой код"? :-) - SciFi(18.09.2020 20:00)
- Язык Си - возможно, самый низкоуровневый из языков высокого уровня, но это таки язык высокого уровня. Это не баг, а фичер. И оптимизация - фичер. - йцyкeн(18.09.2020 21:50)
- Сижу в отладчике, ставлю останов, а он не ставится. Бля. Хорошо, я
не совсем нуб. Убрал всю оптимизацию нафиг. И всё равно на части
кода остановиться нельзя. В ассемблере-то я честно пишу, что надо
что-то в Rn положить. Всё просто и однозначно. Эх. - teap0t(18.09.2020 20:25)
- Сделай переменную volatile. Тогда место кода, где с ней идёт
работа, не будет выоптимизированно. Когда отладку завершишь,
уберёшь. - Nikolay_Po(19.09.2020 14:05)
- В нормальных компиляторах на минимальном уровне оптимизации нет
разницы между volatile и non-volatile. - SciFi(19.09.2020 14:14)
- Наверное, я всегда веду отладку с максимальной оптимизацией. Больше
ошибок и предупреждений вылазит сразу. Уже не понимаю, зачем
собирать код без оптимизации, даже для отладки. Просто прицеплю
volatile-переменную к параметру, в который хочу заглянуть.
Оптимизацию не выключаю. - Nikolay_Po(19.09.2020 14:19)
- gcc -Os -flto такое выдаёт, что отладчиком туда заглядывать
бесполезно, можно сразу шарить в дизассемблере... - SciFi(19.09.2020 14:58)
- По-моему, после LTO, и в дизассемблере бесполезно. Заглянуть в душу оптимизатору может, пожалуй, только его разработчик. Отлаживаю проверяя осциллографом на отладочный выход, на вывод UART, на дисплей, если есть. Ну и само-собой, все предупреждения устраняю, так как жизнь научила, что предупреждение компилятора - латентный баг. - Nikolay_Po(23.09.2020 13:46)
- gcc -Os -flto такое выдаёт, что отладчиком туда заглядывать
бесполезно, можно сразу шарить в дизассемблере... - SciFi(19.09.2020 14:58)
- Наверное, я всегда веду отладку с максимальной оптимизацией. Больше
ошибок и предупреждений вылазит сразу. Уже не понимаю, зачем
собирать код без оптимизации, даже для отладки. Просто прицеплю
volatile-переменную к параметру, в который хочу заглянуть.
Оптимизацию не выключаю. - Nikolay_Po(19.09.2020 14:19)
- В нормальных компиляторах на минимальном уровне оптимизации нет
разницы между volatile и non-volatile. - SciFi(19.09.2020 14:14)
- Сделай переменную volatile. Тогда место кода, где с ней идёт
работа, не будет выоптимизированно. Когда отладку завершишь,
уберёшь. - Nikolay_Po(19.09.2020 14:05)
- Ну да, вмешательство компилятора минимально. А потом он всё
оптимизирует, и погромист недоумевает "где мой код"? :-) - SciFi(18.09.2020 20:00)
- Нет никакой неоднозначности операций. Правила вычислений строго изложены в стандарте. Вы можете пытаться структурировать выражения так, чтобы действовали правила, которые вы знаете, и не действовали те, которые вы не знаете. Но где гарантия, что вы не пропустите какое-нибудь из неизвестных правил? Выход один -- знать правила. - SciFi(18.09.2020 19:03)
- Язык Си очень близок к
- Мне хочется минимизировать неоднозначность операций и снизить
вмешательство компилятора до минимально необходимого. (Пока не
освоился со всем этим). - teap0t(18.09.2020 18:42)
- Не волнуйтесь за компилятор, у него всё будет хорошо. Он сам применит оптимальные инструкции. Ваша забота -- написать код без ошибок в вычислениях. SciFi(110 знак., 18.09.2020 17:34, ссылка)
- На всякий случай скажу банальность: побитные логические операции на
то и побитные, что разряды друг на друга не влияют. Сложение,
вычитание и умножение порождают переносы, при которых младшие биты
влияют на старшие, но никогда наоборот. Только деление и сдвиг
вправо приводят к влиянию старших разрядов на младшие. Поэтому,
если выражение не содержит деления и сдвига вправо, вычисления с
"лишней" разрядностью в соответствии с правилами integer promotion
не влияют на результат. йцyкeн(150 знак., 18.09.2020 18:33)
- Раскройте мысль. Я, конечно, понимаю, что в 16-разрядный регистр 32
разряда не поместятся, и записаны будут только младшие биты.
Собственно, для того и берётся максимальный размер переменной,
чтобы приведение шло исключительно с обрезанием старших разрядов.
Но для компилятора это разве не имеет значения? Может будет
неправильная ассемблерная команда передачи использоваться (пример
условный)? - teap0t(18.09.2020 17:00)
- Ессно, просто бывают случаи, когда приходится явно указывать разрядность. И только тогда это надо делать в исходниках, чтобы бросалось в глаза. Но такое бывает. - Andreas(18.09.2020 12:31)
- Я, собственно, именно из-за пестроты кода полез со всем этим
разбираться. В тексте постоянно встречаются директивы указания
разрядности. Причём мне непонятно, зачем надо заводить 16-разрядную
переменную и постоянно указывать разрядность операций. Можно же
взять 32-разрядную, работать с ней и только перед самой записью в
регистр указать разрядность. Но я же должен убедиться, что всё
правильно понимаю? Поэтому задаю вопросы. Приятно осознавать, что
таки да, правильно понимаю. - teap0t(18.09.2020 15:22)
- Да лааадно.. там же задается битность посылки при ините SPI - POV_(18.09.2020 12:21, )
- Можно цитату из RM? У меня не получается найти. - SciFi(18.09.2020 12:20)
- 27.5.8 Data transmission and reception procedures подраздел Data
packing - Andreas(18.09.2020 12:26)
- Да, кстати. Правильно ли я понимаю, что в этом случае надо
использовать что-либо подобное: (?) teap0t(51 знак., 18.09.2020 18:45)
- Нет, надо как йцукен написал. Но это редчайшее исключение, которое подтверждает правило, что нечего постоянно явно разрядность менять. Andreas(573 знак., 18.09.2020 20:02)
- Нет, неправильно. У вас приведение типа применяется к результату
чтения из регистра, то есть читаются 16 бит, которые потом
обрезаются до 8. Чтобы читать 8, нужно делать так uint8_t data =
*((volatile uint8_t *)&SPIx_DR); - йцyкeн(18.09.2020 19:48)
- Спасибо. А амперсанд зачем? Адрес же! Туплю. - teap0t(18.09.2020 20:38)
- Попробую объяснить подробнее. Приведение типов применяется к значениям, а не к переменным. Возможно, вы хотели бы написать float x; (int)x = 666; но в Си это недопустимо. Допустимо int ix = (int)x; значение x читается как float, потом преобразуется в int. Чтобы обратиться к переменной как к другому типу, нужно применить приведение типа не к самой переменной, а к указателю на неё (это грязный хак). Указатель концептуально состоит из двух частей: адрес некоторой переменной и её йцyкeн(500 знак., 18.09.2020 22:41)
- Спасибо. А амперсанд зачем? Адрес же! Туплю. - teap0t(18.09.2020 20:38)
- По логике - нет, приведение типов и так будет выполнено при
присвоении значения переменной. И дополнительное приведение типа
справа от знака присвоения значения смысла в этом выражении не
имеет. Другое дело если бы переменная была большего размера. Тут я
пока не представляю, как оно сработает. - Nikolay_Po(18.09.2020 19:19)
- ОК. Надо было 32-разрядную переменную заводить. - teap0t(18.09.2020 19:28)
- Офигенно. Спасибо. - SciFi(18.09.2020 13:00)
- Да, кстати. Правильно ли я понимаю, что в этом случае надо
использовать что-либо подобное: (?) teap0t(51 знак., 18.09.2020 18:45)
- 27.5.8 Data transmission and reception procedures подраздел Data
packing - Andreas(18.09.2020 12:26)
- Разумеется, нужно приведение типа, если вы хотите обратиться к
части регистра, например отдельно к старшей и младшей половине
BSRR. Но если вы пишете в регистр целиком, это лишнее. А
(uint32_t)0 - совсем лишнее. И это лишнее не безобидно: компилятору
насрать, а человека, который взялся это читать, шум отвлекает. - йцyкeн(18.09.2020 12:27)
- Если программисту платят за знаки, то вполне годный код. - VLLV(18.09.2020 11:59)
- На SPI stm32f0 вляпался, что 16-битная запись выводит 2 байта, а 8
битная - один. Это описано в RM, но не очевидно. Andreas(118 знак., 18.09.2020 12:14)
- Это говнокод. Не нужны там никакие приведения типа. Ну и регистр
FLASH->SR в хедерах объявлен 32-разрядным, поэтому
"допускающего по документации 8-, 16- и 32-разрядное обращение"
неведомо компилятору. - SciFi(18.09.2020 11:49)
- Пример из жизни... POV_(546 знак., 18.09.2020 11:10, )
- Нифига не наглядный пример. Без кода в студии нещитово. Байки такие
байки. - SciFi(18.09.2020 11:12)
- Новый пример из вчера. XC8... POV_(392 знак., 23.09.2020 13:01, )
- У тебя целое имеет диапазон -32768..32767. И ты пытаешься впихнуть
в него 60*1024. Результат предсказуем. Нужно хотя бы так: 60u*1024. - SciFi(23.09.2020 13:36)
- А, блин, точно! ... ступил )) - POV_(23.09.2020 13:47, )
- У тебя целое имеет диапазон -32768..32767. И ты пытаешься впихнуть
в него 60*1024. Результат предсказуем. Нужно хотя бы так: 60u*1024. - SciFi(23.09.2020 13:36)
- AD7190. Ниже кусок хедера. Без приведения типа keil51 константы
резал по младшим 16 битам... POV_(2451 знак., 18.09.2020 11:18, )
- Кстати, там же int 16-разрядный, верно? Поэтому да, режется, если
при вычислениях тип не расширить до 32 разрядов. Справедливо. - SciFi(18.09.2020 11:20)
- Это свойство компилятора. Очевидно в документации на него написано,
как интерпретируются константы. - BlackMorda(18.09.2020 12:14)
- Это свойство языка Си ващета. - SciFi(18.09.2020 12:15)
- Это реализация компилятора. IAR "int" для AVR считает 16 разрядным,
для ARM - 32разряда. - BlackMorda(18.09.2020 12:19)
- Это стандарт! int равен разрядной сетке, но не менее 16. long равен
разрядной сетке но не менее 32. Брысь за парту. - POV_(18.09.2020 12:20, )
- В каком году впервые появились эти требования? - BlackMorda(18.09.2020 12:28)
- В первом же стандарте. Это было 1989 году. - SciFi(18.09.2020 12:59)
- Лень детально искать. Но в вики ссылка [3] на это.... - POV_(18.09.2020 12:45, , ссылка)
- Для тебя - только что. - POV_(18.09.2020 12:41, )
- В каком году впервые появились эти требования? - BlackMorda(18.09.2020 12:28)
- Это стандарт! int равен разрядной сетке, но не менее 16. long равен
разрядной сетке но не менее 32. Брысь за парту. - POV_(18.09.2020 12:20, )
- Это реализация компилятора. IAR "int" для AVR считает 16 разрядным,
для ARM - 32разряда. - BlackMorda(18.09.2020 12:19)
- Это свойство языка Си ващета. - SciFi(18.09.2020 12:15)
- Это свойство компилятора. Очевидно в документации на него написано,
как интерпретируются константы. - BlackMorda(18.09.2020 12:14)
- Кстати, там же int 16-разрядный, верно? Поэтому да, режется, если
при вычислениях тип не расширить до 32 разрядов. Справедливо. - SciFi(18.09.2020 11:20)
- Новый пример из вчера. XC8... POV_(392 знак., 23.09.2020 13:01, )
- Нифига не наглядный пример. Без кода в студии нещитово. Байки такие
байки. - SciFi(18.09.2020 11:12)
- Вопрос возник из-за такого кода (сразу предлагаю отвлечься от
оскорбительного национализма в определениях): teap0t(911 знак., 18.09.2020 11:45 - 16:55)
- Я протестую против слова "правильно" в этом контексте. Оно вообще
непонятно что означает. - SciFi(18.09.2020 10:54)
- Я хочу задать число, которое будет однозначно интерпретироваться
как 32-разрядная константа в любом контексте (и, скажем, в ПЗУ
будет занимать 4 байта). Если я правильно понял высказанное в
ветке, то объявление teap0t(125 знак., 18.09.2020 10:58)
- Попробуем разобрать высказанные заблуждения. SciFi(1069 знак., 18.09.2020 11:11, ссылка)
- Как я понял, вопрошавший собирался просто использовать константу в
выражениях. Она не будет напрямую присваиваться переменной и,
поэтому, будет храниться именно так, как указано в определении. - Nikolay_Po(18.09.2020 11:12)
- Вы все с ума посходили что ли? Константа нигде не хранится. Это
просто буковки и циферки в исходнике. Хранятся переменные. - SciFi(18.09.2020 11:14)
- Могу только напомнить, что я перехожу с ассемблера на Си, и для
меня числа с трудом отделяются от занимаемого ими места в памяти.
Плюс, речь всё же идёт о встраиваемых системах (да простит меня
fk0), где железо довольно близко. Я не могу к каждой вашей реплике
добавлять тег #ФилософияПрограммирования. Я предлагаю всё же ближе
к теме. Правильный подход виден в ответах VLLV, который просто
показывает ошибку в рассуждении и приводит примеры выявляющие
возможные пути развития teap0t(5 знак., 18.09.2020 11:26)
- А в ассемблере .EQU CCC = 1 сколько места занимало?? - Andreas(18.09.2020 11:29)
- Выдавливайте из себя ассемблер по капле. Постоянная привязка к месту в памяти -- это ментальный тормоз, он мешает мыслить о более интересных абстракциях. - SciFi(18.09.2020 11:29)
- Ну ОК. Речь о ПЗУ. Что если одной переменной присваивается значение другой плюс эта константа? Компилятор по-любому положит эту константу в память, пусть даже как операнд инструкции. Константы могут быть удалены лишь при вычислениях во время компиляции. - Nikolay_Po(18.09.2020 11:22)
- Прошу пардону, а чо мы называем словом хранится? Я например храню
константы (которые первоначально были буковками и циферками в
исходнике) в теле программы, и если меня сильно припрет могу
переписать это тело вместе с этими константами средствами
процессора. Причем получить это новое тело хоть даже через уарт или
кнопочки. - Codavr(18.09.2020 11:21)
- Поэтому надо выражаться недвусмысленно, чтобы тёрки были за смысл,
а не за значение используемых слов. Очевидно же. - SciFi(18.09.2020 11:22)
- Отож. А то развели тут панимаешь. - Codavr(18.09.2020 11:24)
- Поэтому надо выражаться недвусмысленно, чтобы тёрки были за смысл,
а не за значение используемых слов. Очевидно же. - SciFi(18.09.2020 11:22)
- Эт да, но иногда неплохо помочь компилятору намеком. Оба варианта
VLLV дадут варнинг и инфу для размышления программеру. Andreas(312 знак., 18.09.2020 11:21)
- Суффикс L там лишний при любом раскладе (в предположении, что
sizeof(int) == 4). - SciFi(18.09.2020 11:24)
- Нифига не лишний. При переносе на 8-ми-битынй чип, можно с
удивлением обнаружить, что sizeof(int) == 2. - Nikolay_Po(18.09.2020 11:39)
- Хочу увидеть 8-битный чип, на который перенесли регистры от STM32
вместе с хедерами. - SciFi(18.09.2020 11:42)
- Когда одновременно идут проекты на 8 и 32 битниках единообразие
помогает меньше ошибаться и приятней для глаз. ИМХО. - Andreas(18.09.2020 11:47)
- единообразие придумано в stdint.h - VLLV(18.09.2020 12:38)
- Это одна из побудительных причин. STM заявляет, что периферия STM8 и младших моделей STM32 одинаковая. - teap0t(18.09.2020 11:47)
- Когда одновременно идут проекты на 8 и 32 битниках единообразие
помогает меньше ошибаться и приятней для глаз. ИМХО. - Andreas(18.09.2020 11:47)
- Хочу увидеть 8-битный чип, на который перенесли регистры от STM32
вместе с хедерами. - SciFi(18.09.2020 11:42)
- Нифига не лишний. При переносе на 8-ми-битынй чип, можно с
удивлением обнаружить, что sizeof(int) == 2. - Nikolay_Po(18.09.2020 11:39)
- Суффикс L там лишний при любом раскладе (в предположении, что
sizeof(int) == 4). - SciFi(18.09.2020 11:24)
- Могу только напомнить, что я перехожу с ассемблера на Си, и для
меня числа с трудом отделяются от занимаемого ими места в памяти.
Плюс, речь всё же идёт о встраиваемых системах (да простит меня
fk0), где железо довольно близко. Я не могу к каждой вашей реплике
добавлять тег #ФилософияПрограммирования. Я предлагаю всё же ближе
к теме. Правильный подход виден в ответах VLLV, который просто
показывает ошибку в рассуждении и приводит примеры выявляющие
возможные пути развития teap0t(5 знак., 18.09.2020 11:26)
- Вы все с ума посходили что ли? Константа нигде не хранится. Это
просто буковки и циферки в исходнике. Хранятся переменные. - SciFi(18.09.2020 11:14)
- Как я понял, вопрошавший собирался просто использовать константу в
выражениях. Она не будет напрямую присваиваться переменной и,
поэтому, будет храниться именно так, как указано в определении. - Nikolay_Po(18.09.2020 11:12)
- Да. И нет смысла писать именно 0x00000001. Достаточно (uint32_t)1. И скобки можно не ставить, нет более приоритетных операций, хотя и не навредит. - Nikolay_Po(18.09.2020 11:09)
- uint16_t x = FLASH_SR_BSY; или uint64_t y = FLASH_SR_BSY : где тут 32 разряда? - VLLV(18.09.2020 11:07)
- Попробуем разобрать высказанные заблуждения. SciFi(1069 знак., 18.09.2020 11:11, ссылка)
- Я хочу задать число, которое будет однозначно интерпретироваться
как 32-разрядная константа в любом контексте (и, скажем, в ПЗУ
будет занимать 4 байта). Если я правильно понял высказанное в
ветке, то объявление teap0t(125 знак., 18.09.2020 10:58)
- Какой смысл имеет типизация константы не по месту ее применения,
непонятно. А все непонятное неправильно. - VLLV(18.09.2020 10:56)
- Ядро 32 разряда - STM32. Короче, правильно как в оригинале teap0t(92 знак., 18.09.2020 10:52)
- Практически - да, но есть тонкости: uint32_t не одно и то же что и
unsigned long int : в памяти одинаковы, размер одинаков, а типы -
разные. Dingo(314 знак., 18.09.2020 10:56)