KorbenDallas, не говорите ерунды. Обычный C, с ассемблерными вставками. Ну и ещё идиотскими отступами по коду.
Нет. Никакой ерунды. В языке С на уровне файла не допускаются инициализации вида
Код:
const int A = 42; const int B = A; /* <- Ошибка: инициализатор должен быть константным выражением! */
Переменные, объявленные с `const`, в языке С (в отличие от С++) не являются константами времени компиляции и не могут быть использованы там, где требуются константные выражения. В частности, `const` переменные не могут быть использованы для инициализации переменных со статическим классом хранения, то есть не могут быть использованы для инициализации других переменных уровня файла.
Вышеприведенный код (как и код автора вопроса) принимается компиляторами группы GCC/Clang только в качестве нестандартного расширения языка С. Это расширение появилось в GCC начиная с версии 8
подскажите, как сделать так, чтобы переменная, объявленная в одном файле, была видна во всех остальных?
1. В стандартном языке С вам придется идти по классическому пути: создать заголовочный файл с extern-объявлением переменной (без инициализатора).
Код:
extern int a;
А в одном из файлов реализации сделать определение этой переменной (возможно с инициализатором)
Код:
int a = 42;
2. Многие компиляторы языка С (GCC, Clang, MSVC и т.д. и т.п.) поддерживают популярное нестандартное расширение языка С, разрешающее множественные глобальные определения переменных между разными единицами трансляции, при условии, что такие переменные не содержат инициализатора. Это позволяет вам напрямую, прямо в заголовочном файле сделать определение переменной
Код:
int a;
и все. Формально такое определение приводит к множественному определению сущности с внешним связыванием, т.е. к нарушению требований языка. Но вышеупомянутые реализации на этапе линковки просто молча сливают множественные определения в одно, т.е. вы получаете требуемую глобальную переменную.
3. В языке С++ у вас есть либо классический способ (см. 1), либо определение переменной прямо в заголовочном файле как `inline`
Код:
inline int a = 42;
Последний вариант доступен начиная с С++17
Последний раз редактировалось KorbenDallas Чт мар 26, 2020 22:09:32, всего редактировалось 4 раз(а).
KorbenDallas, уже месяц назад написали, что это CodeVision AVR. Там видимо тоже подобные "нестандартные" расширения допускаются. По структуре объявления прерываний и остальному видно прекрасно, что это CVAVR. И прошивку уже в CVAVR собрали на тот вопрос и работает она. Че вы некропостом этим пытаетесь доказать?
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Во-первых, тут нет никакого "доказательства". Доказывать можно теорему. Я лишь упомянул аксиомы языка. Данная тема, напомню, посвящена именно языку С. Во-вторых, "пытаться" я не смогу даже если захочу: я сказал свое слово - все вопросы сразу разрешились. В-третьих, оставьте, пожалуйста, такое понятие как "некропост" там, где ему самое место - в конце девяностых-начале двухтысячных. Такого понятия уже давно не существует. Это, если хотите, уже давно некропонятие ))
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Именно поэтому в С для объявления именно констант (а не "неизменяемых переменных") по-прежнему доминирует `#define`. В ряде случаев можно воспользоваться `enum`. А вот применимость `const` объявлений очень ограничена.
Даже если компилятор позволяет использовать `const` переменные для статической инициализации, он скорее всего не позволит использовать их для указания ширины bit-field, для формирования case-метки, для указания размера не-VLA массива и т.п.
На самом деле, особенно применительно к микроконтроллерами, особой разницы между #define, enum и static const я уже давно не вижу. Оптимизация (-Os) для всех случаев приводит к побайтно идентичному коду, из моего опыта.
А контакты и встраиваемые функции использовать удобнее (по сравнению с теми же макросами, ввиду нулевой разницы на выходе). С ними IDE обычно без проблем работают, давая более адекватные подсказки при автодополнении кода.
особой разницы между #define, enum и static const я уже давно не вижу
разница появляется в тех случаях, когда создаются указатели на эти объявления - хоть Си является языком нестрогой типизации, в большинстве компиляторов предусмотрены варнинги для формально несовпадающих типов, что иной раз сильно выручает.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
На самом деле, особенно применительно к микроконтроллерами, особой разницы между #define, enum и static const я уже давно не вижу. Оптимизация (-Os) для всех случаев приводит к побайтно идентичному коду, из моего опыта.
Это нормально. Сгенерированный код запросто может оказаться идентичным даже если убрать `const` вообще. Если компилятор знает значение переменной в конкретном контексте, то всякий уважающий себя оптимизирующий компилятор не преминет подставить в сгенерированный код ее значение, вместо того, чтобы формировать полноценное обращение к хранилищу. `const` лишь дает ему больше прав.
В данном же случае речь именно о формальной корректности с точки зрения языка.
разница появляется в тех случаях, когда создаются указатели на эти объявления - хоть Си является языком нестрогой типизации, в большинстве компиляторов
Язык С является языком со очень строгой типизацией.
В строгости типизации языки С и С++ фактически идентичны. Различия в типизации между С и С++ сводятся только к возможности неявного преобразования указателей из `void *` в С и возможности неявного преобразования из `int` в `enum` в С (плюс еще ворох нюансов помельче).
предусмотрены варнинги для формально несовпадающих типов, что иной раз сильно выручает.
Все эти "варнинги" - это полноценные ошибки компиляции с точки зрения языка С.
В режиме по умолчанию они не прерывают компиляцию только потому, что используемый вами компилятор в первую очередь предназначен для компиляции огромного наследия старинного и низкокачественного кода, который битком-набит такими ошибками. Исправлять этот старинный "гамнокод" никто не хочет - проще заставить компилятор глотать его с "варнингами".
Хотелось бы пруфов на авторитетов о том, что Си - язык со строгой типизацией.
Ну в первую очередь надо спросить у вас, что вы имели в виду под "нестрогой типизацией" в конкретном случае. Вы ведь вели речь о "ворнингах", то есть имели в виду конкретные ситуации в коде, а не какой-то огульный холивор.
Приводите примеры. А далее - стандарт языка С. Авторитетнее некуда.
Сравните синтаксис Паскаля и Си, и вы уразумеете, что значит строгая типизация. В паскале целочисленной переменной вы не присвоите значение действительной переменной, например. В Си - легко, и даже варнинга не будет. В общем, рекомендую. А, говорят, Ада ещё и паскалю 100 очков даст. Си - это просто вакханалия, один char чего стоит...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Сравните синтаксис Паскаля и Си, и вы уразумеете, что значит строгая типизация. В паскале целочисленной переменной вы не присвоите значение действительной переменной, например. В Си - легко, и даже варнинга не будет.
Если вы имели в виду возможность неявного преобразования плавающих типов к целым в С, то да - в этом отношении язык С нестрого типизирован.
Добавлено after 3 minutes 4 seconds: Можете и boolean попробовать, и операции над целыми числами... Паскаль не позволит скомпилировать код, где применяются "несовместимые" типы, Си позволит. Это и есть нестрогая типизация. А варнинг не ошибка, а костыль, вытекающий из "нюансиков" Си.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Можете и boolean попробовать, и операции над целыми числами... Паскаль не позволит скомпилировать код, где применяются "несовместимые" типы, Си позволит. Это и есть нестрогая типизация.
Нет, это лишь частные вольные предположения о том, что является "строгой типизацией", а что является "нестрогой типизацией". Банальный интернетный холивор для пионэров. Неинтересно.
А варнинг не ошибка, а костыль, вытекающий из "нюансиков" Си.
Никаких "нюансиков Си" тут нет. Это действительно "костыли", но "костыли" вытекающие лишь из пожеланий и девичьих мечт разработчиков конкретного компилятора. Никакого отношения к самому языку С эти "костыли" не имеют даже отдаленно.
В языке С нет никаких "варнингов" и нет никаких "ошибок" в принципе. А есть только диагностические сообщения, выдаваемые в ситуациях, когда их требует стандарт языка. В языке С все такие диагностические сообщения равны между собой. А что там написал в сообщении ваш компилятор (слово "варнинг" или слово "ошибка") - это целиком и полностью студенческая самодеятельность вашего компилятора. Я уже ясно объяснил выше, откуда у этой самодеятельности ноги растут.
Знать особенности вашего компилятора (т.е. распознавать ситуации, когда он рапортует формальные "ошибки" как "варнинги") - это ваша обязанность. Некоторые компиляторы могут помочь вам в этом (напр. ключ `-pedantic-errors` в GCC и Clang), а с некоторыми вам придется опираться исключительно на собственные знания. Язык С, как таковой, здесь ни в чем не виноват.
Это потому, что флейм тут исключительно ваш. Вы то прыгаете в надъязыковые теоретические классификации, то разглагольствуете про какие-то конкретные компиляторные "варнинги". Это совершенно разные, никак не связанные темы. Добиться от от вас конкретного объяснения, о чем же вы ведете речь, мне пока не удалось. Пока вы не определитесь с тем, что сказать-то хотели, ваши разглагольствования будут восприниматься как флейм.
Мои басни - ни что иное как точное, четкое и авторитетное описание свойств языка, который является темой данной ветки. "Ликбез", как вы его назвали.
В предыдущем сообщении речь о каких-то "костылях", "варнингах" и т.п. В ответ на проведенный мной ликбез по этой теме вы вывалили сюда ссылку на какую-то статью, которая к этой теме вообще никаким боком не относятся. "Флейм", как вы его назвали.
Возникает очевидный вопрос: вы точно не перепутали "ликбез" с "флеймом"? ))
(Что касается статьи по ссылке в самостоятельном рассмотрении: это не "ликбез", а предложенный автором доморощенный вариант классификации. Вполне стройный и логичный, малость устаревший. Не хуже, не лучше других. Авторов этих, каждый со своим вариантом - хоть залейся. Как я уже сказал, мне эти теоретические холиворы не интересны.)
Так процитируйте спецификацию Си! То место, где говорится о типизации и её строгости (или сильности). Хватит уже собственных интерпретаций! Можете Кернигана процитировать, тоже сойдёт за авторитет.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 38
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения