- •Глава 1. Сведения о компиляторе
- •1.1.Введение
- •1.2. Основные вопросы
- •1.3. Описание компилятора и документация
- •1.4. Компилятор и другие средства разработки
- •1.5. Набор возможностей компилятора
- •1.5.1. Стандарт ANSI Си
- •1.5.2. Оптимизация
- •1.5.3. Поддержка стандартной ANSI библиотеки
- •1.5.4. Гибкие модели памяти
- •1.5.5. Драйвер компилятора
- •Глава 2. Отличия 16-битового компилятора от ANSI
- •2.1. Введение
- •2.2. Основные вопросы
- •2.3. Отличия ключевых слов
- •2.3.1. Определение атрибутов переменных
- •2.3.2. Определение атрибутов функций
- •2.3.3. Inline функции
- •2.3.4. Переменные в определенных регистрах
- •2.3.4.1. Определение глобальных регистровых переменных
- •2.3.4.2. Определение локальных регистровых переменных
- •2.3.5. Комплексные числа
- •2.3.6. Целые размером в двойное слово
- •2.3.7. Ссылки на тип с помощью typeof
- •2.4. Отличия операторов
- •2.4.1. Метки как значения
- •2.4.2. Условные операторы с опущенными операндами
- •2.4.3. Диапазоны case
- •2.5. Отличия выражений
- •2.5.1. Двоичные константы
- •Глава 3. Использование компилятора в командной строке
- •3.1. Введение
- •3.2. Основные вопросы
- •3.3. Обзор
- •3.4. Соглашение для имен файлов
- •3.5. Опции
- •3.5.1. Опции, специфические для устройств dsPIC
- •3.5.2. Опции для управления типом результатов
- •3.5.3. Опции для управления диалектом Cи
- •3.5.5. Опции для отладки
- •3.5.6. Опции для управления оптимизацией
- •3.5.7. Опции для управления препроцессором
- •3.5.8. Опции для ассемблера
- •3.5.9. Опции для компоновщика
- •3.5.10. Опции для поиска в каталогах
- •3.5.11. Опции для соглашений по генерации кода
- •3.6. Переменные окружения
- •3.7. Предопределенные имена макро
- •3.9. Компиляция нескольких файлов в командной строке
- •3.10. Особенные символы
- •Глава 4. Среда периода исполнения
- •4.1. Введение
- •4.2. Основные вопросы
- •4.3. Адресное пространство
- •4.4. Запуск и инициализация
- •4.5. Пространства памяти
- •4.6. Модели памяти
- •4.6.1. Ближние и дальние данные
- •4.6.2. Ближний и дальний код
- •4.7. Расположение кода и данных
- •4.8. Программный стек
- •4.9. Использование стека в Си
- •4.11. Соглашения по вызову функций
- •4.11.1. Параметры функции
- •4.11.2. Возвращаемое значение
- •4.12. Соглашения о регистрах
- •4.13. Двоичная инверсия и модульная адресация
- •4.14.1. Загрузочные и защищенные константы
- •4.14.2. Строковые константы как аргументы
- •4.14.3. Переменные с квалификатором const в безопасной Flash
- •4.14.4. Модель совместимости объектов
- •Глава 5. Типы данных
- •5.1. Введение
- •5.2. Основные вопросы
- •5.3. Представление данных
- •5.4. Целые
- •5.5. С плавающей точкой
- •5.6. Указатели
- •Глава 6. Дополнительные типы указателей Си
- •6.1. Введение
- •6.2. Управляющие PSV указатели
- •6.2.1. Определение данных для управления доступом PSV
- •6.2.2. Управляемый доступ PSV
- •6.2.3. Рассмотрение ISR
- •6.3. PMP указатели
- •6.3.1. Инициализация PMP
- •6.3.2. Объявление нового пространства памяти
- •6.3.3. Определение переменных в пространстве PMP
- •6.4. Внешние указатели
- •6.4.1. Объявление нового пространства памяти
- •6.4.2. Определение переменных во внешнем пространстве
- •6.4.3. Определение способа доступа к пространству памяти
- •6.4.3.2. Функции записи
- •6.4.4. Пример внешней памяти
- •Глава 7. Файлы поддержки устройства
- •7.1. Введение
- •7.2. Основные вопросы
- •7.3. Файлы заголовков процессора
- •7.4. Файлы определения регистров
- •7.5. Использование SFR
- •7.6. Использование макросов
- •7.6.1. Макросы настройки битов конфигурации
- •7.6.2. Макросы использования ассемблера inline
- •7.6.3. Макросы выделения памяти данных
- •7.6.4. Макросы объявления ISR
- •7.7. Адресация EEDATA из Си - только для dsPIC30F
- •7.7.1. Доступ к EEDATA через PSV
- •7.7.2. Доступ к EEDATA посредством команд TBLRDx
- •7.7.3. Дополнительные источники информации
- •Глава 8. Прерывания
- •8.1. Введение
- •8.2. Основные вопросы
- •8.3. Написание программы обработки прерывания
- •8.3.1. Рекомендации по написанию ISR
- •8.3.3. Кодирование ISR
- •8.3.4. Использование макросов для объявления простых ISR
- •8.4. Запись вектора прерывания
- •8.4.1. Вектора прерываний dsPIC30F (без SMPS)
- •8.4.3. Вектора прерываний PIC24F
- •8.4.4. Вектора прерываний dsPIC33F/PIC24H
- •8.5. Сохранение контекста в ISR
- •8.7. Вложенные прерывания
- •8.8. Разрешение/запрещение прерываний
- •8.9. Разделение памяти между основной программой и ISR
- •8.9.1. Разработка проблем
- •8.9.2. Разработка решений
- •8.9.3. Пример приложения
- •8.10. Использование PSV в ISR
- •Глава 9. Совместное использование ассемблера и Си
- •9.1. Введение
- •9.2. Основные вопросы
- •9.3. Смесь переменных и функций на ассемблере и Си
- •9.4. Использование ассемблера inline
- •Приложение A. Определяемое реализацией поведение
- •A.12. Квалификаторы
- •A.13. Деклараторы
- •A.14. Операторы
- •A.17. Сигналы
- •A.18. Потоки и файлы
- •A.20. Errno
- •A.22. Abort
- •A.23. Exit
- •A.24. Getenv
- •A.25. Система
- •A.26. Strerror
- •Приложение B. Встроенные функции
- •B.2. Список встроенных функций
- •Приложение C. Диагностика
- •Приложение D. Компиляторы Си PIC18 и PIC24/dsPIC
- •D.6. Использование стека
- •D.11. Банк доступа
- •D.12. Inline ассемблер
- •D.13. Прагмы
- •D.14. Модели памяти
- •D.15. Соглашения о вызове
- •D.16. Код запуска
- •D.17. Управляемые компилятором ресурсы
- •D.18. Оптимизация
- •D.20. Определяемое реализацией поведение
- •D.21. Битовые поля
Руководство пользователя по MPLAB® компилятору Си для PIC24 и dsPIC®
Глава 2. Отличия 16-битового компилятора от ANSI
2.1. Введение
В этой главе обсуждаются синтаксические отличия языка Cи, поддерживаемого
|
компилятором MPLAB Cи для PIC24 и dsPIC (бывшего MPLAB C30) и стандарта ANSI |
||
|
Cи 1989. |
|
. |
2.2. |
Основные вопросы |
|
|
|
A |
||
|
Вопросы, обсуждаемые в этой главе: |
||
|
|
||
|
• Отличия ключевых слов |
|
|
|
• Отличия операторов |
|
|
|
• Отличия выражений |
|
|
2.3. |
Отличия ключевых слов |
|
|
|
Эта секция описывает различия ключевых слов между чистым ANSI Cи и Cи, |
||
|
|
Wilson |
|
принятым компилятором для 16-битовых устройств. Новые ключевые слова являются частью базовой реализации GCC, и обсуждение в этой секции основано на стандартной документацииbyGCC, приспособленной для специфического синтаксиса и семантики портированного на 16-битовую архитектуру GCC компилятора.
• Определение атрибутов переменных
•• ОпределениеTranslatedатрибутов функций Inline функции
• Переменные в определенных регистрах
• Комплексные числа
• Целые размером в двойное слово
• Ссылки на тип с помощью typeof
2.3.1. Определение атрибутов переменных
Ключевое слово компилятора __attribute__ позволяет вам определять специальные атрибуты переменных или полей структуры. За этим ключевым словом следует спецификация атрибута внутри двойных круглых скобок. В настоящее время поддерживаются следующие атрибуты переменных:
• address (addr)
• aligned (alignment)
•boot
•deprecated
•fillupper
•far
•mode (mode)
•near
•noload
•packed
•persistent
|
|
© 2008 Microchip Technology Inc. |
DS51284H(ru) стр. 2-1 |
16-битовый компилятор Си. Руководство
• reverse (alignment) |
|
|
• section ("section-name") |
|
|
• secure |
|
|
• sfr (address) |
|
|
• space (space) |
|
|
• transparent_union |
|
|
• unordered |
|
|
• unused |
|
|
• weak |
. |
|
|
|
|
Вы можете также определить атрибуты с помощью __ (двойного подчеркивания) |
||
перед и после каждого ключевого слова |
A |
вместо |
(например, __aligned__ |
||
aligned). Это позволяет вам использовать их в файлах заголовка не беспокоясь о
возможности макро с тем же самымWilsonименем.
Для того, чтобы определить несколько атрибутов, разделите их запятыми в пределах двойных круглых скобок, например:
__attribute__ ((aligned (16), packed)).
Примечание Важна последовательность в использовании атрибутов переменных в проекте. Например, если переменная определена в файле A с атрибутом far, и объявлена extern в файле B без far, то это может привести к ошибке компоновки.
быть использован совместно с атрибутом section. Это можно применить, чтобы начать группу переменных с заданного адреса:
Атрибут address определяетby абсолютный адрес переменной. Этот атрибут может
int baz attribute__((section("mysection")));
int foo attribute__((section("mysection"),address(0x900))); intTranslatedbar attribute__((section("mysection")));
Переменная с атрибутом address не может быть помещена в пространство auto psv (см. атрибут space() или опцию -mconst-in-code); попытка сделать так вызовет предупреждение и компилятор поместит переменную в пространство PSV. Если переменная должна быть установлена в секцию PSV, адрес должен быть адресом памяти программ.
int var attribute__ ((address(0x800)));
alig (alignment)
Этот атрибут определяет минимальное выравнивание для переменной, выраженное в байтах. Выравнивание должно быть степенью двойки. Например, декларация:
int x attribute__ ((aligned (16))) = 0;
заставляет компилятор поместить глобальную переменную x на 16-байтовой границе. В устройстве dsPIC это могло бы быть использовано совместно с выражением asm, чтобы иметь доступ к командам DSP и адресным режимам, которые требуют выравнивания операндов.
Как в предыдущем примере, вы можете явно определить выравнивание (в байтах), если Вы хотите, чтобы компилятор использовался его для данной переменной. Кроме этого, вы можете опустить величину выравнивания и просто попросить компилятор произвести максимально полезное выравнивание переменной для устройства dsPIC. Например, вы могли бы записать:
short array[3] __attribute__ ((aligned));
Всякий раз, когда вы опускаете величину выравнивания в спецификации атрибута выравнивания, компилятор автоматически устанавливает выравнивание для объявленной переменной на самое большое выравнивание для любого типа данных
DS51284H(ru) стр. 2-2 |
© 2008 Microchip Technology Inc. |
Глава 2. Отличия 16-битового компилятора от ANSI
в используемой машине, которое в случае устройства dsPIC составляет два байта (одно слово).
Атрибут aligned может только увеличить выравнивание; но вы можете уменьшить его задавая packed (см. ниже). Атрибут aligned конфликтует с атрибутом reverse. Использование их вместе приводит к ошибке.
Атрибут aligned может применяться совместно с атрибутом section. Это позволит использовать выравнивание в поименованной секции. По умолчанию, когда никакая секция не определена, компилятор создает уникальную секцию для переменной. Это обеспечивает компоновщику наилучшую возможность для удовлетворения ограничениям выравнивания без использования внутреннего заполнения, что может иметь место, если в пределах одной и той же выровненной секции появляются
другие определения. |
. |
boot |
A |
Этот атрибут может быть использован,Wilsonчтобы определить защищенные переменные в сегменте загрузки (Boot segment, BS) RАМ:
int __attribute__((boot)) boot dat[16];
Переменные, определенные в BS RAM не будут инициализированы на запуске. Следовательно все переменные в BS RAM должны быть инициализированы с использованием inline кода. Если для переменной boot определены начальные значения, будет выдано диагностическое сообщение.
int __attribute__((boot)) time = 0; /* не поддерживается */
|
by |
int __attribute__((boot)) time2; |
|
void __attribute__((boot)) foo() |
|
{ |
|
time2 = 55; /* начальное значение должно присваиваться явно */ |
|
} |
|
deprecated |
|
Атрибут depreca |
приводит к тому, что декларация в которой он использован, |
intTranslatedattribute ((__deprecated__)) i; int mai () {
специально распознается компилятором. Когда используется deprecated функция или переменная, компилятор выдаст предупреждение.
Определение deprecated тем не менее действует и, следовательно, присутствует в любом объектном файле. Например, компиляция следующего файла:
return i;
}
вызовет предупреждение:
deprecated.c:4: warning: `i’ is deprecated (declared at deprecated.c:1)
i, тем не менее, будет определена в результирующем объектном файле обычным способом.
fillupper
Этот атрибут может быть использован, чтобы определить, что старший байт переменной хранится в секции space(prog).
Например:
int foo[26] __attribute__((space(prog),fillupper(0x23))) = { 0xDEAD };
© 2008 Microchip Technology Inc. |
DS51284H(ru) стр. 2-3 |
16-битовый компилятор Си. Руководство
заполнит старшие байты массива foo значением 0x23 вместо 0x00. foo[0], однако, будет инициализирован значением 0xDEAD.
Опция командной строки -mfillupper=0x23 выполнит ту же функцию.
far
Атрибут far сообщает компилятору, что переменная необязательно должна быть расположена в ближнем пространстве данных (начальные 8 KB), (т.е., переменная может быть расположена в любом месте памяти данных).
mode (mode)
Этот атрибут задает тип данных для объявлений, как какой угодно тип,
соответствующий заданному аргументом атрибута mode. Это фактически позволяет |
||||||
|
|
|
|
|
A |
точкой в соответствии с их |
вам запрашивать целый тип или тип с плавающей. |
||||||
разрядностью. Допустимые значения для mode следующие: |
||||||
|
|
|
|
|
|
|
|
Mode |
|
Разрядность |
|
Тип для компилятора |
|
|
|
|
|
|
|
|
|
QI |
|
8 |
бит |
|
char |
|
HI |
|
16 бит |
|
int |
|
|
|
|
|
|
|
|
|
SI |
|
32 |
бита |
|
long |
|
|
|
|
|
|
|
|
DI |
|
64 |
бита |
|
long long |
|
|
|
|
|
|
|
|
SF |
|
32 |
бита |
|
float |
|
|
|
|
|
|
|
|
DF |
|
64 |
бита |
|
long double |
|
|
Wilson |
|
|||
|
Этот атрибут полезен |
для написания переносимого кода для всех поддерживаемых |
||||
компилятором |
устройств. Например, следующая |
функция складывает два |
||||
32-битовых целых со знакомbyи возвращает 32-битовый знаковый целый результат: typedef int __attri ute__((__mode__(SI))) int32;
int32 add32(int32 a, int32 b) Translated{ return(a+b);
}
Вы можете также определить режим byte или __byte__, чтобы обозначить режим, соответствующий однобайтовому целому, word или __word__ для режима однословного целого, и pointer или __pointer__ для режима, используемого, чтобы представлять указатели.
near
Атрибут ear сообщает компилятору, что переменная расположена в ближней области пространства данных (первые 8 KB памяти данных). К таким переменным иногда можно получить более эффективный доступ, чем к переменным, которые не расположены (или о которых неизвестно, что они расположены) в ближней области пространства данных.
int num attribute__ ((near));
noload
Атрибут noload указывает, что пространство будет выделено для переменной, но начальное значение не должно быть загружено. Этот атрибут может быть полезным, если приложение должно загружать переменную в память во время исполнения, например, из последовательной EEPROM.
int table1[50] __attribute__ ((noload)) = { 0 };
packed
Атрибут packed определяет, что переменная или поле структуры должны иметь минимальное возможное выравнивание — один байт для переменной и один бит для поля, если только вы не задаете большую величину в атрибуте aligned.
DS51284H(ru) стр. 2-4 |
© 2008 Microchip Technology Inc. |
Глава 2. Отличия 16-битового компилятора от ANSI
Вот структура, в которой поле x упаковано так, чтобы оно немедленно следовало за полем a:
struct foo
{
char a;
int x[2] __attribute__ ((packed));
};
Примечание Архитектура устройства требует, чтобы слова были выровнены по границе |
||
|
|
. |
|
|
четных байтов, так что следует внимательно отнестись к использованию |
|
|
A |
|
|
атрибута packed, чтобы избежать ошибок времени исполнения. |
persistent |
Wilson |
|
Атрибут |
|
|
persistent определяет, что переменная не должна быть |
||
инициализирована или очищена при запуске. Переменная с атрибутом persistent могла бы быть использована, чтобы хранить информацию о соcтоянии, которая останется в силе после сброса устройства.
int last_mode __attribute ((persistent));
Такие «устойчивые» данные обычно не инициализируются во время исполнения Си программы. Тем не менее, после холодного старта «устойчивые» данные не могут
содержать полезную информацию. Этот пример кода показывает, как безопасно |
|
инициализировать подобные данные: |
|
#include "p24Fxxxx.h" |
|
|
by |
int last_mode __attribute__((persistent)); |
|
int main() |
|
{ |
|
Translated |
|
if ((RCONbits.POR == 0) && (RCONbits.BOR == 0)) {
/* last mode в силе */ } else {
/* инициализируем "устойчивые" данные */ last mode = 0;
}
}
reverse (alignment)
Атрибут reverse определяет минимальное выравнивание для последнего адреса переменной плюс один. Выравнивание определено в байтах и должно быть степенью двойки. Обратно выровненные переменные могут быть использованы для декрементирования по модулю буферов на ассемблере dsPIC. Этот атрибут может быть полезным, если приложение определяет в Си переменные, доступ к которым будет осуществляться из ассемблера.
int buf1[128] __attribute__ ((возобновлять(256)));
Атрибут reverse конфликтует с атрибутами aligned и section. Попытка наименовать секцию для обратно выровненной переменной будет проигнорирована с предупреждением. Ошибкой является определение атрибутов revers и aligned для одной и той же переменной. Переменная с атрибутом reverse не может быть помещена в пространство auto_psv (см. атрибут space() или опцию -mconst-in-code); попытки сделать это вызывают предупреждение и компилятор помещает переменную в пространство PSV.
© 2008 Microchip Technology Inc. |
DS51284H(ru) стр. 2-5 |
16-битовый компилятор Си. Руководство
section ("section-name")
По умолчанию компилятор размещает сгенерированные объекты в таких секциях, как, например, .data и .bss. Атрибут section позволяет вам нарушить такое течение событий, определив для переменной (или функции) конкретную секцию.
struct array {int i[32];}
struct array buf __attribute__ ((section("userdata"))) = {0};
Атрибут секции конфликтует с атрибутами address и reverse. В обоих случаях имя секции будет проигнорировано с предупреждением. Этот атрибут также может
конфликтовать с атрибутом space. Подробности см. в описание атрибута space. |
|
secure |
. |
|
A |
Этот атрибут может быть использован, чтобы определить защищенные переменные |
|
в безопасном сегменте (Secure Segment, SS) RAM: |
|
|
Wilson |
int __attribute__((secure)) secure_dat[16];
Переменные определенные в SS RAM не будут инициализированы на запуске. Следовательно, все переменные в SS RAM должны быть инициализированы c использованием inline кода. Определение начальных значений для переменных с атрибутом secure вызовет выдачу диагностического сообщения.
Строковые константы могут быть присвоены переменным с атрибутом secure с использованием inline кода, но они требуют дополнительной обработки компилятором. Например:
char *msg __attribute__((secure)) = "Hello!\n"; /* не поддерживается */ char *msg2 __attribute__((secure));
void __attribute__((secure)) foo2()
{ |
*msg2 = "Goodbye..\n";by |
|
|
/* значение присваивается явно */ |
|
} |
Translated |
|
|
|
В этом случае, место для строковой константы должно быть выделено в пространстве памяти, которое доступно в содержащей ее безопасной функции. Компилятор расположит строку в секции констант psv, определенной для безопасного сегмента.
sfr (address)
Атрибут sfr сообщает компилятору, что переменная является SFR и также определяет адрес времени исполнения для переменной, используя параметр address.
extern volatile int __attribute__ ((sfr(0x200)))u1mod;
Использование описателя extern потребовалось для того, чтобы избежать ошибки.
Примечание По соглашению, атрибут sfr используется только в файлах заголовках процессора. Чтобы определить обычную переменную пользователя по специфическому адресу, используйте атрибут address совместно с far или near, чтобы правильно задать режим адресации.
space (space)
Обычно компилятор размещает переменные в общем пространстве данных. Атрибут space может быть использован, чтобы заставить компилятор расположить переменную в специфических местах памяти. Пространства памяти обсуждаются дополнительно в разделе 4.5 «Пространства памяти». Следующие аргументы применимы в атрибуте space:
DS51284H(ru) стр. 2-6 |
© 2008 Microchip Technology Inc. |
Глава 2. Отличия 16-битового компилятора от ANSI
data
Размещает переменную в общем пространстве данных. Переменные общего пространства данных доступны с использованием обычных операторов Си. Это расположение по умолчанию.
xmemory - только для dsPIC30F/33F DSCs
Размещает переменную в пространстве данных X. Переменные в пространстве данных X доступны с использованием обычных операторов Си. Пример расположения переменной посредством xmemory:
int x[32] __attribute__ ((space(xmemory)));
A |
|
Размещает переменную в пространстве данных. |
Y. Переменные в пространстве |
данных Y доступны с использованием обычных операторов Си. Пример |
|
расположения переменной посредством ymemory: |
|
Wilson |
|
int y[32] __attribute__ ((space(ymemory)));
prog
Размещает переменную в программном пространстве, в секции определенной для исполняемого кода. Переменные в программном пространстве не могут быть доступные с использованием обычных операторов Си. Доступ к ним должен быть явно организован программистом, обычно с использованием inline команд ассемблера для доступа к таблицам, или с использованием окна видимости программного пространства.
Размещает переменнуюby в программном пространстве, в управляемой компилятором секции, определенной для доступа через окно автоматической видимости программного пространства. Переменные в пространстве auto_psv
могут быть прочитаны (но не записаны) с использованием обычных операторов TranslatedСи и должны быть пригодными к размещению в пространстве максимальным размером 32К. При использовании space(auto_psv) невозможно назначать
имя секции с использованием атрибута section; любое имя секции будет проигнорировано с предупреждением. Переменная в пространстве auto_psv не может быть размещена по заданному адресу или иметь обратное выравнивание.
Примечание Переменные, размещенные в секции auto_psv, не загружаются в память данных при запуске. Этот атрибут может быть полезным для уменьшения использования RAM.
dma - только для PIC24H и ds PIC33F
Размещает переменную в DMA памяти. Переменные в DMA памяти могут быть доступные с использованием обычных операторов Си и периферии DMA. builtin dmaoffset() (см. «16-Bit Language Tools Libraries», DS51456), может быть использована, чтобы найти правильное смещение для
конфигурирования DMA периферии.
#include <p24Hxxxx.h>
unsigned int BufferA[8] __attribute__((space(dma))); unsigned int BufferB[8] __attribute__((space(dma))); int main()
{
DMA1STA = __builtin_dmaoffset(BufferA); DMA1STB = __builtin_dmaoffset(BufferB); /* ... */
}
© 2008 Microchip Technology Inc. |
DS51284H(ru) стр. 2-7 |
16-битовый компилятор Си. Руководство
psv
Размещает переменную в программном пространстве, в секции, определенной для доступа через окно видимости программного пространства. Компоновщик расположит секцию так, чтобы переменная могла быть доступна целиком используя единственную установку регистра PSVPAG. Переменные в пространстве PSV не управляются компилятором и не могут быть доступны с использованием обычных операторов Си. Доступ к ним должен быть явно организован программистом, обычно с использованием inline команд ассемблера для доступа к таблицам, или с использованием окна видимости
программного пространства. |
. |
eedata - только для dsPIC30F |
|
|
|
Рамещает переменную в пространстве EEData. Переменные в пространстве |
|
|
A |
EEData не могут быть доступны с использованием обычных операторов Си.
Размещает переменную в пространствеWilson памяти, определенном пользователем. Подробнее см. п. 6.4. «Внешние указатели».
Доступ к ним должен быть явно организован программистом, обычно с
использованием inline команд ассемблера для доступа к таблицам, или с использованием окна видимости программного пространства.
pmp
Размещает переменную в памяти вне кристалла, подключенной средствами периферии PMP. Подробнее, см. п. 6.3. «PMP указатели».
external
Этот атрибут, примененныйbyк параметру функции, имеющему тип union, означает,
что соответствующий аргумент может иметь тип любого члена союза, но аргумент
должны иметь одинаковое машинное представление, что необходимо для правильной передачи аргумента.
передается так, как будто его тип были тем же, что и у первого члена союза. АргументTranslatedпередается в функцию используя соглашения вызова первого члена транспарентного союза, а не соглашения вызова самого союза. Все члены союза
unordered
Атрибут unordered указывает, что расположение этой переменной может переместиться относительно других переменных в пределах исходного файла Си.
const i attribute__ ((unordered)) i; unused
Этот атрибут, примененный к переменной, означает, что переменная предположительно может быть неиспользована. Компилятор не выдаст для нее предупреждения о неиспользованной переменной.
weak
Атрибут weak приводит к тому, что декларация создает «слабый» символ. Слабый символ может быть заменен глобальным определением. Когда weak применяется к ссылке на внешний символ, такой символ не будет необходим для компоновки. Например:
extern int __attribute__((__weak__)) s;
int foo {
if (&s) return s;
return 0; /* возможна некоторая другая величина */
}
DS51284H(ru) стр. 2-8 |
© 2008 Microchip Technology Inc. |
Глава 2. Отличия 16-битового компилятора от ANSI
В вышеприведенной программе, если s не определен некоторым другим модулем, программа все же будет скомпонована, но s не будет присвоен адрес. Оператор условия проверяет, что s определен (и возвращает величину, если она есть). В противном случае возвращается 0. Есть много применений для этой возможности, в основном для обеспечения общего кода, который может быть скомпонован с необязательной библиотекой.
Атрибут weak может быть применен как к функциям, так и к переменным: extern int __attribute__((__weak__)) compress_data(void *buf);
int process(void *buf) { |
|
|
|
if (compress_data) { |
|
|
if (compress_data(buf) == -1) /* ошибка */ |
|
|
|
. |
|
} |
A |
|
/* обработка буфера */ |
|
|
Wilson |
|
} |
|
|
|
|
|
В вышеуказанном коде функция compress_data будет использоваться только если она прикомпонована из какого-то другого модуля. Решение, использовать или нет данную возможность, переносится со времени компиляции на время компоновки.
Воздействие атрибута weak на определение является более сложным и требует для описания многочисленных файлов:
/* weak1.c */
int __attribute__((__weak )) i;
void foo() { |
by |
|
|
i = 1; |
|
} |
|
Translated |
|
/* weak2.c */ int i;
extern void foo(void);
void bar() { i = 2;
}
m in() { foo(); bar();
}
Здесь определение i в weak2.c приводит к тому, что символ становится строго определенным. Ошибка компоновки не будет выдана и обе переменных i будут ссылаться на ту же ячейку памяти. Память, выделенная для версии i из weak1.c будет недоступна.
Не существует проверок, чтобы убедиться, что обе версии i имеют тот же тип; изменение типа i из weak2.c на float не повлияет на возможность компоновки, но поведение функции foo будет непредсказуемо. foo запишет величину в младшие разряды нашей 32-битовой переменной с плавающей точкой. И наоборот, изменение типа слабого определения i в weak1.c на тип float может вызвать катастрофические результаты. Мы запишем 32-битовое значение с плавающей
© 2008 Microchip Technology Inc. |
DS51284H(ru) стр. 2-9 |
