![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_pattern.png)
![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_default_photo.png)
razrab83
Участник-
Постов
383 -
Зарегистрирован
-
Посещение
-
Победитель дней
3
Весь контент razrab83
-
не сказал бы. не аргумент. вот смотрите, на вскидку, цитата из справочника по СИ, Бочков и Субботин Ниже коментарии.... и далее много текста про то, какой может быть int и как зависит от архитектуры. Т.е. для int показали "деталей, в том числе implementation-defined", а для char нет. Как читатель должен понимать, из этого, что char - тоже зависит от реализации? Меня это и удивило.
-
можно пример, где char в с/с++ поменяет размер?
-
Да, так и есть. Я знаю, что стандарт не определяет char знаковый или нет, и это отдано на откуп компиляторам. И да, я писал для х86. Я знаю, что gcc без указаний char интепретирует его как signed char. Вернее там, где я писал - там так и было. И более того, во всяких учебниках/справочниках по СИ - кругом "диапазон char от -128 до +127". Ни какого упоминания о компиляторах и/или архитектурах и что что-то может быть не так. И кто-бы мог подумать, что переехав с десктопа на малину, оставаясь всё в том же linux и с тем же gcc и той же версии - char поменяет знак!?
-
поэтому я таково ответа не давал. не надо мне приписывать того, чего я не говорил.
-
Вот это поворот!!! Вот это мастерское переобувание на 180°. Ровно об это я и говорил с самого начала. Даже ericN привёл пример, как должен выглядеть хидер в данном случае. работодатель хотел посмотреть как я решу поставленную задачу. я её решил. работодатель был удовлетворён. вполне годное решение. Может кто-нибудь написал бы лучше... но тем не менее - это ваш include.h. Вы в нем хозяин. Вы его написали и выдали в "общий проект". Если кто-то захочет использовать - он подключит ваш include.h в свой .с или даже в свой .h (ему нет необходимости его корректировать). Прогер этот ваш include.h может себе включить в любом порядке с другими заголовками. Очерёдность a.h, b.h или include.h ни как не повлияет на "соберётся или нет проект". Я же говорю о другом. Написал прогер myCalc.c и myCalc.h. Я взял его расчет и подключил в свой проект. подтянул myCalc.h. Запускаешь сборку - ошибка. Неизвестный тип T_type_some. Ищешь где этот тип описан. Нашел. Подключил myInclude.h в .с. Ошибка - не определёно 10 типов из myInclude.h. Ещё подключаешь 5 хидеров - ошибка, не определено 50 типов....... когда это всё собрал - получилось в .с 10 инклуде вместо одного. и далее.... по какой-нибудь причине поменял очерёдность - всё рухнуло.
-
что ни разу нет? По дефолту, т.е. если ни каких специальных указаний компилятору не давать - char знаковый. Плохого в этом то, что неявные приведения типа - это источник проблем. При таком неявном приведении типа вам даже си компилятор дает предупреждение. Не было бы в это ни чего плохого - не было бы предупреждений. В с++ убрали неявные приведения типа оставили их только для совместимости с си, но добавили касты и рекомендуют приведения делать кастами.
-
как раз таки я последовал рекомендациям производителей софта и включил FreeRTOS.h перед task.h
-
Попробовал. Да, действительно, task.h перед FreeRTOS.h - не собирается. Но, в task.h в самом начале #ifndef INC_TASK_H #define INC_TASK_H #ifndef INC_FREERTOS_H #error "include FreeRTOS.h must appear in source files before include task.h" #endif получил этот вывод. Но во первых, тут авторы позаботились и сделали проверку и вывод. Программисту не нужно заниматься сыском. Во-вторых что мешало сделать так? #ifndef INC_TASK_H #define INC_TASK_H #include "FreeRTOS.h" #ifndef INC_FREERTOS_H #error "include FreeRTOS.h must appear in source files before include task.h" #endif Добавил #include "FreeRTOS.h" в #include "timers.h", #include "queue.h", #include "semphr.h" - теперь тусуй их в любой последовательности и всё собирается. далее... вот ваша ссылка на TI Да, прямо уже согласился с порядком... но в глубине мыслей, а почему FreeRTOSConfig.h не вставить в FreeRTOS .h? Зачем они его вынесли?.... открываю проект с FreeRTOS, инклуде такие #include "FreeRTOS.h" #include "timers.h" #include "queue.h" #include "semphr.h" #include "task.h" #include "event_groups.h" А где же FreeRTOSConfig.h??? Провалился в FreeRTOS.h и там /* Application specific configuration options. */ #include "FreeRTOSConfig.h" Ну правильно же сделали. Может раньше в старых версиях ртос FreeRTOSConfig.h не было в FreeRTOS.h. Сейчас он там есть. Добавить в "task.h" #include "FreeRTOS.h" - и ни какой зависимости от порядка следования include нет.
-
Да конечно! Расскажите тем, кто пользуется автоматическим форматированием кода, или авторам clang format. Сlang format расставляет инклуде так, чтобы удобно было читать программисту, группирует их, делает очень аккуратный и красивый код. И вот clang format вас точно не спросит, в какой последовательности расставлять инклуде. начните с того, чтобы от порядка инклуде сборка не зависела. Это так просто. Начнет получаться.
-
Коллега сказал эту фразу, именно в контексте своего хидера. Пишут хидеры, так, что для их использования перед ними нужно включать обязательно др хидер. И считают так и надо писать. Более того... вот код *.с всё в том же контексте... #include "myParams.h" #include "project.h" #include "flag.h" void funk(void) { ... } код собирается. вы видете, что тут перед #include "flag.h" нет #include "global.h", а он собирается. Как так? аказываицо в #include "project.h" включон другой инклуде, а тот ещё один.. и в тот ещё один... ещё цепочка в 10-ок и вот там #include "global.h". Человек пишет какое нибудь API... решил использовать переменную типа T_type_some - так ты либо определи её, либо сделай инклуде на неё. Пусть оно будет в *.h через 10 вложений, но, если в *.c кто-то включет твоё одно единственное #include "flag.h", у компилятора не должно возникнуть вопроса, что такое T_type_some, этот flag.h должен подтянуть всё необходимое, что он использует.
-
вопрос остался - а кто-то так делает? Смысл этой этой строки? беру слова обратно. в том проекте была локальная переменная. возможно "повезло" и в иар7 под неё выделялась память в который случайно был ноль.
-
вот ещё... прямо с пылу-жару... иногда мк-си-прогеры всётаки пишут хидеры, в которых объявляют структуры. вот пример flag.h #ifndef __SYSTEM_H__ #define __SYSTEM_H__ T_type_some *p; #endif Хидер конечна больше, я укоротил для наглядности. Это СИ. Что такое T_type_some? Это тип данных (или структура), которые определены в global.h Я включаю в свой *.с #include "flag.h" - ошибка, компилятор не знает что такое T_type_some. Подхожу к автору хидера flag.h (у него несколько десятков лет стажа), спрашиваю - WTF? Он в ответ: "-Нужно в *.с перед #include "flag.h" делать #include "global.h", и если эти инклуде поменять очерёдность, то не собрётся. " фэйспалм. Причем, он уверен, что си именно так работает и так задумано. Он считает, что в СИ очерёдность инклуде строгая, и если её не соблюдать, то код не соберётся. Нужно быть внимательным к очерёдности и правильно её делать. Я потом в его проекте как-то неаккуратно применил шланг-формат, который поправил очерёдность #include - компиялтор бедный ТАК ПОКРАСНЕЛ!!!.... чуть ли не в каждой стоке кода ошибки. Ну что это?
-
оффтопа немного МНОГО... прям наболело надо в ближайший понедельник взять и отменить СИ. за чем нужны коты нужен си? писать всё в с++. времена, когда код с++ был тяжелее ушли. кому-то наболел когда-то goto и он написал разгромный труд о запрете goto, у меня наболело копаться в чужом коде си, да и вообще работать в си. Вот студент, учится по специальности "микропроцессоры". Что он по выходу знает? p-n-n переходы, автоматы мили/мура, работу триггера/ключа/И-НЕ и прочей логики. Да, их (по своей учебе сужу) учат программированию. Общим приципам. Учат asm-у. Учат писать без асма сразу в машинных кодах. Но программирование у таких специалистов - это побочный продукт. Часто они становятся превосходными схемотехниками. Но иногда им приходится свои же поделки программировать. С++ их не учили, да и там высоки порог вхождения. Си тоже не учили, но там попроще и вот они начинают творить... за частую написать программу на датчик - это простой проект. Поэтому они пишут его в одного, а не в команде. Набраться навыков не у кого. И вот они пишут такой говнокод.... и пишут... потом проект становиться сложнее - какойнить контроллер... и далее далее... матереют... и продолжают писать и писать говнокод.... как это пораждается... во первых какой нить главный while() - это акын простыней. главный while() - это >10000 строк. там всё! ..... леса, реки, люди, кони.... во вторых пишут парсер на протокол - там switch() - на 1000 кейсов, в каждом кейсе может быть switch ещё на 10-20 кейсов и в них вложения for/if/for/for/switch.... ещё и отступ 8 пробелов - форматирование съезжает за экран... ну как так писать!? Ну не пишите вы функцию больше экрана. в идеале 5 строк. у вас в протоколе 300 команд - вот и 300 case. Ну сделайте std::map<>, или массив с указателем на функцию и ключом. Функция должна просматриваться одним взглядом от начало до конца без скролинга. Это улучшает читаемсоть и понимание. Опять же.... пишут в отдельном *.с файле int calc(float y).... хидеры принципиально не делают (кому они нужны, без них всё работает). совершенно в др *.с файле вызывают calc(123) - компилятор си дает ворнинг на имплицит и линкер потом всё линкует. Попробуй найди где этот calc()? Пишите хидеры. Вот проект, дали мне его, надо добавить одно окошко. По идее мне нужно написать myDialog.c и myDialog.h, в каком нибудь ОДНОМ месте подключить myDialog.h и там сделать вызов API моего диалога. Как тут делается... пишется ТОЛЬКО myDialog.с чтобы диалог собрался, нужно в др. месте добавить виджеты диалога др. в др. Т.е. в myDialog.c просто глобальная переменные - лейба, кнопка и канва. А в др. месте в глобальном ините нужно на эту канву добавить мои кнопку и лейбу. Ещё в одном месте, картинку, ещё в другом месте ещё что-то. Нужно провести изменения в 10-ти файлах. кругом через extern сделать доступные глобальные переменные, а имплицитные функции си проглотит. Спагетти. проект состоит чуть менее, чем полностью из глобальных переменных. в любом файле может быть объявлена глобальная переменная, потом в любом др *.с файле делается exten - и ВСЁ. Вы представляете!!! В каком нибудь драйвере на LСD делается переменная на текущую строку int row, или в драйвере питания переменная на текущее питание float U. а других местах делается просто extern int row и extern float U. Причем так делается не из-за незнания, а наоборот, "опытные" МК-прогеры "знают", что именно так и надо делать, надо объявлять переменную в не тела функции и в исходниках делать extern.... Я "проходил интернатуру" в команде на прогеров для ПК, меня учили - в любой программе должна быть всего одна глобальная переменная. Больше не должно быть. Сейчас понимаю - это хороший принцип. Когда говоришь автору "-У тебя тут глобальная переменная!", он в ответ "- и что? так и должно быть." А когда я устраняю ворнинг, на меня смотрят как на ненормального. Ни кто не обращяет внимания на ворнинги. Собирается?! Работает - зачем париться. У большинства МК-прогерров нет ни какой культуры написания ПО. Я не знаю как сейчас, может плотно учать в ВУЗах программированию, но опотные мк-си-прогеры - это какойто треш!!! Прежде чем писать самостоятельно ПО для МК, нужно пару лет поработать в команде с наставниками по написанию ПО. Возможно/лучше для ПК. Какую-то интернатуру устроить. Чтобы прогеру МК привили хоть какую-то минимальную культуру написания ПО. пишут int a = -3; unsigned short b = 2; if(a > b) { } Стандарт СИ оговаривает такой код, делает неявное приведение и делает сравнение. Мне когда на собеседе дали такую задачу и спросили "-В иф зайдет?", я сказал, "-Я не знаю правильный ответ, но это говнокод. Так писать нельзя и я так не пишу. Если я встречу такой код, я открою справочник, посмотрю куда преобразует СИ и сделаю ЯВНОЕ приведени типа." Они (мк-си-прогеры), не то что так пишут - они на собеседовании дают такие задачи, ожидая, чтобы претендент знал куда будет приведени и так писал. (кстати, мой ответ понравился, был защитан, я меня приняли). дальше бомблю.... IAR... какой-то идиот сделал там галочку считать char беззнаковым. По дефолту в си он знаковый. Да, компиляторы си/с++ допускают такой ключ... но, вот ты поставил эту галку. написал мегафункционал. твой функционал дернул коллега себе в код, а у него другая иде и там этой галки нет. У него будет char знаковый. Даже может код будет работать... год, два... а потом рухнет. Вообще, лучше использовать uint8_t и т.п. Но мк-прогеры самоучки. Лень писать unsigned - длинное слово, поэтому галку ставят и не парятся. А пришел новичек, подхватил проект и он даже не знает, что в си по дефолту char знаковый. Этот новичек ... 2....3 ....10 лет пишет программы и он знает, что char по дефолту беззнаковый. Использование этих галочек - это источник проблем. Ещё одна говноособенность иара... неинициализируемая переменная без явных указаний инитится нулём. Опять же... мк-самоучки пишут код... кто-то по незнанию думает что после int i; ш всегда будет 0, т.к. так должно быть в си, а кто-то это знает, и специально не инитит нулём, т.к. иар сам проинитит. И что? потом код собрали в др метсе - и прога легла. у меня был опыт, когда я в чужом проекте добавил запятую в сообщении и пересобрал. Исходный был в иар 7, я пересобрал в иар 8. Отправили программу - она переодически виснет. Не часто, но болезнено. нашел причину - использование неинициализируемой переменной. всегда явно инициализируйте переменные. sizeof(int) и sizeof(char). "до буквы докапались". А кто-то так пишет? Реально в жизни кто-то в коде пытается определить размер символа? Так можно написать сишнику, чтобы специально подложить мину сипипишнику.
-
Спасибо! Проблема решена. Расходимся.
-
сделал холоворд в кубе на пуре СИ (gcc) int main(void) { HAL_Init(); sdfds(); SystemClock_Config(); ... Компилятор выдал ошибку (не линкер, а компилятор) ВЫДАЛ ВОРНИНГ!!!, а линкер ошибку. arm-none-eabi-gcc "../Core/Src/main.c" warning: implicit declaration of function 'sdfds' с++ на такое выдают ошибку, а си ворнинг. Конечно для меня это дико. дабылКлик по ошибке компилятора - и улетаешь на нужную строку кода. ДабылКлик по ошибке линкера и .... НИЧЕГО. погуглил.... есть в gcc "-Wimplicit-function-declaration", а ещё есть "-pedantic-errors". pedantic-errors генеригует на подобную дичь, как и пологается, ошибку компилятора. Но это "загнивающие" gcc. А что касается православного тру иаровского компилятора, то у него нет ни pedantic-errors, ни Wimplicit-function-declaration. Заседание продолжается..... кто знает, как в иаровском компиляторе заставить генерировать ошибку на implicit function declaration? ps оптимизация отключена. а в стандарте си описано на что компилятор должен выдавать ошибки, а на что ворненги?
-
IAR 8.5, stm32f*, пишу код в *.с файле void myFunc(void) { drfkgjklj(); } drfkgjklj() - такая функция ни где не определена и ни где не объявлена. Запускаю сборку. Компилятор выдает Какой к черту implicitly? Это всегда так в си, или где-то в настройках проекта лядский флаг стоит? Я ожидаю, что компилятор выдаст Error[Pe020]: identifier "drfkgjklj" is undefined
-
Подтверждаю. Только не в кубе, а в eclipse. Программа с ошибкой, но эклипс в таргет льёт последнюю прошивку неизвестно что! Это можно исправить? Это не то что костыль, это совсем не то, что нужно. В проекте 100500 файлов. Запустил компиляцию, "ушел кофе пить". Вернулся - отлаживаешь. Поправил в одном файле "запятую" -надо пересобрать и проверить. Нужно перекомпилировать всего один маленький файл исходника и слинковать новую прошивку. Мне не нужно делать Clean и пересобирать весь проект в полный рост. Нужно только пересобрать те файлы, в которых были изменения. Причем в кансоли проскакивает вывод компиляции очень быстро, и за частую иногда даже не успеваешь заметить "красные" строки.... текст пробежал - и переключились на загрузку.
-
На вскидку Эмулятор рукоятки JLINK, эмулятор модели V9, адаптер, STM32 ARM MCU, гарантия качества - 2 272,92 ₽ стоит как 22 свистка ST-Link. Да и еще там же комент Офигенный совет!
-
возможно потому, что между net.port и net.dhcpOn есть "дырка" в 2 байта из-за выравнивания. А также после ___reserved__1 "дырка" в 2 байта из-за выравнивания. поробуйте обрамить структура прагмой pragma pack(2) .... pragma pack()
-
Не совсем понятно. Вы в настройках выбрали подключение через SWD. в командной строке появилось -d. Всё правильно. Если выбрать JTAG, то -d должна пропасть. У вас аппаратно как ваш h743 подключен? через swd или jtag?
-
а что стоит после ST-LINK_gdbserver.exe? -d должна встать если выбран SWD. У вас он выбран. перезалил https://disk.yandex.ru/d/iB7Z-THZ_8dk5A
-
stvp https://disk.yandex.ru/d/pwdYRHejJ0GPtA ps дожили, на яндекс диск можно попасть только через vpn.