jcxz 242 5 мая, 2021 Опубликовано 5 мая, 2021 · Жалоба 2 часа назад, razrab83 сказал: дупликэйт дифинишин Так ведь в приличных домах исходниках принято принимать меры против множественного включения: #ifndef ASD_H #define ASD_H int const array[] = {1,2}; #define SIZE_ARRAY (sizeof(array)) #endif Или у вас IAR какой-то неправильный, раз у всех работает, а у вас - нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
razrab83 21 5 мая, 2021 Опубликовано 5 мая, 2021 · Жалоба 1 час назад, jcxz сказал: Так ведь в приличных домах исходниках принято принимать меры против множественного включения: #ifndef ASD_H #define ASD_H int const array[] = {1,2}; #define SIZE_ARRAY (sizeof(array)) #endif Или у вас IAR какой-то неправильный, раз у всех работает, а у вас - нет. А вы не видите какой косяк в этом коде, не компилируя его? "дупликэйт дифинишин" - извините за мой французкий duplicate definition. Какая взаимосвязь между "множественным определением" и "множественным включением"? Естественно во всех хидерах есть #ifndef ASD_H. И? В приличных домах обычно, переменные объявляют в хидерах, определяют в исходниках. Включите #include "asd.h" в несколько *.с, компилятор в каждом *.с определит array (мне это зачем?), линкер дает законную ошибку дупликэйт дифинишин Error[Li006]: duplicate definitions for "array"; Цитата раз у всех работает ps Научитесь держать слово за себя. Все другие сами за себя скажут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 5 мая, 2021 Опубликовано 5 мая, 2021 · Жалоба 3 минуты назад, razrab83 сказал: А вы не видите какой косяк в этом коде, не компилируя его? В чём именно "косяк"? 3 минуты назад, razrab83 сказал: Включите #include "asd.h" в несколько *.с, компилятор в каждом *.с определит array (мне это зачем?), линкер дает законную ошибку дупликэйт дифинишин Error[Li006]: duplicate definitions for "array"; И почему у меня на кучу таких включений никаких ни ошибок ни варнингов не выдаётся, а у вас - выдаются? Может стоить поискать причину? У себя. 3 минуты назад, razrab83 сказал: ps Научитесь держать слово за себя. Все другие сами за себя скажут. Кроме вас о подобной проблеме больше никто не пишет, соответственно - проблема только у вас. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
razrab83 21 5 мая, 2021 Опубликовано 5 мая, 2021 (изменено) · Жалоба 2 часа назад, jcxz сказал: В чём именно "косяк"? Нарушено правило ODR. Я же разжевал в чем косяк? См мой пост выше. Или вы издеваетесь? Модератор, дайте бан jcxz на пару недель, за издевательство. Может знание по С/С++ подтянет. 2 часа назад, jcxz сказал: И почему у меня на кучу таких включений никаких ни ошибок ни варнингов не выдаётся, а у вас - выдаются? Вы хотите сказать, что если вы в двух исходных файлах определите две глобальные переменные с одинаковым именем, то ваш линкер это проглотит? Если да, то вы не на с/с++ пишите. Вам тут не место на другой форум. 2 часа назад, jcxz сказал: Кроме вас о подобной проблеме больше никто не пишет, соответственно - проблема только у вас. Ну во первых у меня нет подобной проблемы, т.к. я подобный говнокод не генерирую. Во вторых, если кто и "оступиться", то компилятор линкер сообщит проблему и она легко правиться, и ни нужно ни куда ни чего писать. ну и в третих.... встречаются начинающие программисты, которые не могут справиться с Li006, они пишут об этом, просят помощь, даже на электрониксе. Поищите. ps собрал холоворд на gcc с вашим кодом - тоже самое, даже код ошибки такой же. Цитата multiple definition of `array' collect2.exe: error: ld returned 1 exit status make: *** [makefile:65: Li006.elf] Error 1 6 часов назад, Andrew_Q сказал: Если перейти к указателю, то проинициализируется extern const int array_size; int *qwe = &array_size; Только я уже не уверен это ли требуется. Уже не требуется. Сделал именно через указатель. Всё равно спасибо! Изменено 5 мая, 2021 пользователем razrab83 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 5 мая, 2021 Опубликовано 5 мая, 2021 · Жалоба 16 минут назад, razrab83 сказал: Вы хотите сказать, что если вы в двух исходных файлах определите две глобальные переменные с одинаковым именем, то ваш линкер это проглотит? Если да, то вы не на с/с++ пишите. Вам тут не место на другой форум. Может не стоит посылать других куда-то, чтобы самому не быть посланным? И я вроде достаточно внятно написал, чтобы ещё раз повторять одно и то же. Это "проглатывают" и IAR и VS как минимум. И другие компиляторы должны. А если у вас с этим проблема (не у меня) - то может стоить выпрямить руки? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 5 мая, 2021 Опубликовано 5 мая, 2021 · Жалоба 19 минут назад, razrab83 сказал: Если да, то вы не на с/с++ пишите Как бы ни было смешно, но в приведенном виде этот код должен компилироваться на плюсах - там const имеет внутеннее связывание, т.е. по-умолчанию все глобальные const-переменные как бы static. А если бы переменная была не const и не была проинициализирована - то в сях бы компилилось, а в плюсах нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
razrab83 21 6 мая, 2021 Опубликовано 6 мая, 2021 · Жалоба 15 часов назад, Сергей Борщ сказал: код должен компилироваться на плюсах - там const имеет внутеннее связывание, т.е. по-умолчанию все глобальные const-переменные как бы static Да, в плюсах const int array[] объявленный 2 раза в разных исходниках собирается, без const нет. В си с const - нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
juvf 17 6 мая, 2021 Опубликовано 6 мая, 2021 · Жалоба 19 часов назад, jcxz сказал: В чём именно "косяк"? Стыдно должно быть за такие вопросы. 17 часов назад, razrab83 сказал: Вы хотите сказать, что если вы в двух исходных файлах определите две глобальные переменные с одинаковым именем, то ваш линкер это проглотит? На си нет конечно, звездит. Что там jcxz и чем компилирует - неизвестно. У меня Iar-arm и mingw подавились: multiple definition of `array' ... mingw32-make[1]:... Error 1 Это в стандарте прописано. Пруф - ISO/IEC 9899:2017 6.9 External definitions Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 65 6 мая, 2021 Опубликовано 6 мая, 2021 · Жалоба 17 часов назад, Сергей Борщ сказал: Как бы ни было смешно, но в приведенном виде этот код должен компилироваться на плюсах - там const имеет внутеннее связывание, т.е. по-умолчанию все глобальные const-переменные как бы static. Точно так. И это хорошо работает для простых объектов встроенных типов, а вот с массивами может получиться уже не очень красиво: если попытаться взять адрес массива (а это просто сослаться на него), то компилятор вынужден будет разместить массив в памяти. Если такое делается во многих единицах трансляции, то будет пачка копий одного и того же массива, что не есть гуд. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rkit 4 6 мая, 2021 Опубликовано 6 мая, 2021 · Жалоба 22 minutes ago, dxp said: то компилятор вынужден будет разместить массив в памяти Размещением в памяти занимается линкер, а не компилятор. И не размещать несколько копий одного и того же не является проблемой на этом этапе. Хотя не знаю, что там происходит на самом деле. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 6 мая, 2021 Опубликовано 6 мая, 2021 · Жалоба 4 часа назад, dxp сказал: Если такое делается во многих единицах трансляции, то будет пачка копий одного и того же массива, что не есть гуд. Естественно - лучше так не делать для больших массивов. Но для небольших - ничего страшного, пускай даже образ увеличится на несколько сотен байт или на килобайт. Зато доступ к дубликатам может происходить быстрее, чем если будет один экземпляр. А в настоящее время - скорость выполнения обычно важнее чем размер образа. 4 часа назад, rkit сказал: И не размещать несколько копий одного и того же не является проблемой на этом этапе. Хотя не знаю, что там происходит на самом деле. Да, например IAR имеет соответствующую опцию компоновщика "--merge_duplicate_sections". Но почему-то она не работает - сейчас попробовал и не смог заставить выполнять объединение копий, хотя по мануалу - должна удалять дубликаты. PS: Нашел как заставить компоновщик IAR удалять дубликаты const-объектов: __ro_placement int const volatile array[] = {1,2}; И будет только одна копия во флешь. Доступ будет немного медленнее, чем в варианте с дубликатами. Но таким образом можно даже большие массивы объявлять/определять в .h-файлах без дублей. Естественно должен быть также ключ ликера "--merge_duplicate_sections" (через соответствующую галку в опциях проекта). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 65 7 мая, 2021 Опубликовано 7 мая, 2021 · Жалоба 18 часов назад, rkit сказал: Размещением в памяти занимается линкер, а не компилятор. И не размещать несколько копий одного и того же не является проблемой на этом этапе. Хотя не знаю, что там происходит на самом деле. Выделением памяти занимается компилятор — именно он решает, что (какие объекты) и как (в каких секциях) размещать в ней. Линкер лишь потом компонует это всё (мапит объектные секции на физические сегменты) и разрешает связи (подставляет реальные адреса в "плейсхолдеры). Если вы напишете в заголовочном файле (С++) // header1.h const int x = 5; и потом будете ссылаться на этот константный объект любым способом, кроме случаев, где потребуется адрес, то любой современный вменяемый компилятор просто не размещает этот объект в памяти и использует только его значение — это становится возможным именно благодаря внутреннему связыванию констант в С++. И линкер тут ничего уже "размещать" не сможет, ибо нечего. Создание (размещение) объектов в памяти "не его ума дело". Да, некоторые современные линкеры достаточно интеллектуальны, чтобы производить достаточно сложную доводку финального образа (например, LTO), но существа дела это не меняет: появится (разместится в памяти) объект или не появится, решает не линкер, а компилятор. 15 часов назад, jcxz сказал: Естественно - лучше так не делать для больших массивов. Но для небольших - ничего страшного, пускай даже образ увеличится на несколько сотен байт или на килобайт. Зато доступ к дубликатам может происходить быстрее, чем если будет один экземпляр. А в настоящее время - скорость выполнения обычно важнее чем размер образа. Если объект (массив) будет размещён в памяти, то разницы по скорости доступа не будет, и, следовательно, толку от дубликатов по скорости никакого нет. Только оверхед по ресурсам. Вот если, скажем, описаны небольшие массивы, и обращения к их элементам компилятор может разрешить на этапе компиляции, т.е. использовать значения, не размещая сами массивы в памяти, то тогда профит есть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 7 мая, 2021 Опубликовано 7 мая, 2021 · Жалоба 6 часов назад, dxp сказал: Если объект (массив) будет размещён в памяти, то разницы по скорости доступа не будет, и, следовательно, толку от дубликатов по скорости никакого нет. Серьёзно? Всё теоретизируете? Пример из практики (IAR). 1-й случай: Массив tJSUri - в виде нескольких копий (по одной на каждую единицу компиляции): LogCR(COL_GREEN ">>> " COL_PURPLE "JSON in. " COL_BLUE "%s", tJSUri[jmemArg]); 0x.... 0x.... ADR.W R0,tJSUri 0x78E1 LDRB R1,[R4, #+3] 0xF850 0x1021 LDR R1,[R0, R1, LSL #+2] 0x.... 0x.... ADR.W R0,?_15 0x.... 0x.... BL _Z12ServiceLogCRPKcz 2-й случай: Тот же самый участок исходника, но массив tJSUri - в виде одной копии (единый на все единицы компиляции): LogCR(COL_GREEN ">>> " COL_PURPLE "JSON in. " COL_BLUE "%s", tJSUri[jmemArg]); 0x.... 0x.... LDR.W R0,??DataTable86_20 0x78E1 LDRB R1,[R4, #+3] 0xF850 0x1021 LDR R1,[R0, R1, LSL #+2] 0x.... 0x.... ADR.W R0,?_11 0x.... 0x.... BL _Z12ServiceLogCRPKcz Как видим - простое вычисление адреса относительно PC (команда ADR) заменилось на загрузку адреса по смещению к PC (LDR), что несколько медленнее. Что и закономерно, так как компилятор не знает куда компоновщик разместит тело tJSUri, а значит не может использовать ADR, приходится использовать LDR. PS: Это ещё не учитывая того, что во 2-м случае дополнительно занимается 4 байта под хранение указателя на tJSUri, который грузит LDR. Что (для мелких массивов) ещё больше снижает стоимость варианта с несколькими копиями. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 7 мая, 2021 Опубликовано 7 мая, 2021 · Жалоба 2 hours ago, jcxz said: несколько медленнее Для LogCR(), наверное, страсть как актуально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 65 7 мая, 2021 Опубликовано 7 мая, 2021 · Жалоба 5 часов назад, jcxz сказал: Серьёзно? Всё теоретизируете? Какая в % разница по скорости выполнения этого кода? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться