Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Keil и с99
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
sidy
Здравствуйте, уважаемые форумчане. В проекте, созданном в Keil MDK-ARM 4.54 есть три файла main.c. pwm.h и pwm.c. В файле pwm.h объявленна переменная i. При добавлении в main.c и pwm.c строки #include "pwm.h" возникает ошибка: Proj.axf: Error: L6200E: Symbol i multiply defined (by main.o and pwm.o). В опциях проекта C/C++ в строке Misc Controls задано --С99. Как я понимаю в с99 можно объявлять переменную в нескольких местах, а на этапе компиляции переменная заменится одной. Но почему-то не удается. Подскажите пожалуйста, что я делаю не так?
_Артём_
Цитата(sidy @ Oct 29 2012, 16:25) *
Здравствуйте, уважаемые форумчане. В проекте, созданном в Keil MDK-ARM 4.54 есть три файла main.c. pwm.h и pwm.c. В файле pwm.h объявленна переменная i.

Как объявлена?
Код
int i;

или
Код
extern int i;

?
Второй вариант допустим.
Цитата(sidy @ Oct 29 2012, 16:25) *
При добавлении в main.c и pwm.c строки #include "pwm.h" возникает ошибка: Proj.axf: Error: L6200E: Symbol i multiply defined (by main.o and pwm.o).

Так и должно быть: если "pwm.h" инклудится в оба Си-шных файла, то переменная i получается объявленной в обеих файлах. И получаете ошибку.

Цитата(sidy @ Oct 29 2012, 16:25) *
В опциях проекта C/C++ в строке Misc Controls задано --С99.

С99 здесь нипричом.

Цитата(sidy @ Oct 29 2012, 16:25) *
Как я понимаю в с99 можно объявлять переменную в нескольких местах, а на этапе компиляции переменная заменится одной.

Это как? Приведите пример...

Цитата(sidy @ Oct 29 2012, 16:25) *
Подскажите пожалуйста, что я делаю не так?

Объявляйте переменные в с-файлах:
pwm.c
Код
int SomeVar;


pwm.h
Код
#ifndef _PWM_H_
#define _PWM_H_

extern int SomeVar;

#endif
sidy
Спасибо за разъяснение. А что означает _PWM_H_?
_Артём_
Цитата(sidy @ Oct 29 2012, 17:04) *
Спасибо за разъяснение. А что означает _PWM_H_?


Это называется Include guard.
SyncLair
Цитата(sidy @ Oct 29 2012, 19:04) *
Спасибо за разъяснение. А что означает _PWM_H_?

УУ biggrin.gif ) -- это стандартная мегафича препроцессора для того, чтобы не вставлять много раз заголовочный файл.
XVR
Цитата(_Артём_ @ Oct 29 2012, 17:35) *
Это как? Приведите пример...
Есть такая буква в С (но не в С++!)
Стандарт C99, параграф 6.9.2 External object definitions
Цитата
2 A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition. If a translation unit contains one or more tentative definitions for an
identifier, and the translation unit contains no external definition for that identifier, then
the behavior is exactly as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation unit, with an initializer
equal to 0.

Параграф 6.2.2 Linkages of identifiers
Цитата
1 An identifier declared in different scopes or in the same scope more than once can be
made to refer to the same object or function by a process called linkage.21) There are
three kinds of linkage: external, internal, and none.

2 In the set of translation units and libraries that constitutes an entire program, each
declaration of a particular identifier with external linkage denotes the same object or
function. Within one translation unit, each declaration of an identifier with internal
linkage denotes the same object or function. Each declaration of an identifier with no
linkage denotes a unique entity.


sidy
Вот вот Параграф 6.2.2 Linkages of identifiers. Все же не понятно, почему подключив --с99 в keil'e мне не удается объявлять переменную с одним и тем же названием в разных файлах.
XVR
Цитата(sidy @ Oct 30 2012, 13:15) *
Все же не понятно, почему подключив --с99 в keil'e мне не удается объявлять переменную с одним и тем же названием в разных файлах.
Видимо Keil не соотвествует в этом месте стандарту. Кстати, это место в стандарте появилось задолго до С99, и собственно в С99 оно помеченно как кандидат на удаление в следующих редакциях.

sidy
По ссылке http://www.keil.com/support/man/docs/armcc...ef_BABIBBFI.htm сказано что компилятор поддерживает стандарты:
ISO/IEC 9899:1999. The 1999 International Standard for C.
и
ISO/IEC 9899:1999/Cor 2:2004. Technical Corrigendum 2
Как раз в первом стандарте есть параграф 6.2.2
XVR
Цитата(sidy @ Oct 30 2012, 22:03) *
По ссылке сказано что компилятор поддерживает стандарты:
ISO/IEC 9899:1999. The 1999 International Standard for C.
и
ISO/IEC 9899:1999/Cor 2:2004. Technical Corrigendum 2
Зафайлите им баг - пусть чинят компилятор rolleyes.gif
yurmala
Кстати, тоже столкнулся с с этой директивой. Давненько уже отписался разрабам Keil. Но как-то они последние месяцы компилятором не шибко заняты.
demiurg_spb
У меня никогда не было подобных сообщений ни c одним компилятором, включая keil.
Приведите минимальный тестовый случай при котором проявляется ваша жалоба. Т.е конкретно содержимое файлов
module1.c
module1.h
module2.c
module2.h
урезанное до минимума.
Сергей Борщ
QUOTE (demiurg_spb @ Nov 6 2012, 14:12) *
У меня никогда не было подобных сообщений
Просто вы никогда не пользовались этой "фичей" С. Смотрите сообщение №6.
Вот вам урезанный минимум:

module1.c:
CODE
int A;



module2.c:
CODE
int A;
ViKo
Прочитав (как сумел) цитаты из стандарта, показанные XVR, я не увидел, что переменные можно несколько раз определять в проекте, без квалификатора extern во всех файлах, кроме того, где переменная инициализируется (или не инициализируется, а просто определяется = резервируется место под нее).
XVR
Цитата(ViKo @ Nov 6 2012, 16:22) *
Прочитав (как сумел) цитаты из стандарта, показанные XVR, я не увидел, что переменные можно несколько раз определять в проекте, без квалификатора extern во всех файлах, кроме того, где переменная инициализируется (или не инициализируется, а просто определяется = резервируется место под нее).

Параграф 6.2.2 часть 2. В нем под external linkage понимается глобальная видимость переменных из модуля, а не слово extern в их определении. Т.е. просто int A; будет иметь этот самый external linkage.
ViKo
Цитата(XVR @ Nov 6 2012, 15:39) *
Параграф 6.2.2 часть 2. В нем под external linkage понимается глобальная видимость переменных из модуля, а не слово extern в их определении. Т.е. просто int A; будет иметь этот самый external linkage.

А из чего это следует (понимать так)?
demiurg_spb
Цитата(Сергей Борщ @ Nov 6 2012, 15:36) *
Просто вы никогда не пользовались этой "фичей" С. Смотрите сообщение №6.
Вот вам урезанный минимум:
module1.c:
Код
int A;

module2.c:
Код
int A;
Понятно, я всегда использую static в таких случаях.
Проверил только что на mingw-gcc-4.6.2 - съел молча.
ViKo
Цитата(demiurg_spb @ Nov 6 2012, 16:10) *
Понятно, я всегда использую static в таких случаях.

Так при static это будут разные переменные.
_Артём_
Цитата(demiurg_spb @ Nov 6 2012, 15:10) *
Понятно, я всегда использую static в таких случаях.

Их тогда две будет
XVR
Цитата(ViKo @ Nov 6 2012, 16:45) *
А из чего это следует (понимать так)?

Из пункта 1го того же параграфа. Ну и из остального текста, который в цитату не попал rolleyes.gif
ReAl
Об этом тут уже говорили
ViKo
Цитата(ReAl @ Nov 6 2012, 19:14) *
Об этом тут уже говорили

ЧуднО! rolleyes.gif
Но ни у K&R, ни у Шилдта об этом ни гу-гу.
demiurg_spb
Цитата(ViKo @ Nov 6 2012, 17:19) *
Так при static это будут разные переменные.
Да я этого обычно и хочу. А когда хочу другого то extern использую.
У меня чёткий стандарт кодирования либо static либо extern, другого для глобальных переменных не дано.
Короче понял я суть "проблемы", всё как всегда - каждый сам себе Буратино...
sidy
Я нашел в Keil'e как можно выбрать gcc компилятор, вместо armcc. GCC 4.6 поддерживает объявление переменных, как было описано выше. Нажмите для просмотра прикрепленного файла
Но при попытке скомпилировать проект возникает ошибка: --- Error: failed to execute 'arm-noeabi-as'
Может кто подскажет, что должно быть написано в GNU-Tool-Prefix. По умолчанию стоит arm-noeabi-
Сергей Борщ
QUOTE (sidy @ Nov 29 2012, 16:50) *
По умолчанию стоит arm-noeabi-
Зависит от того, какая сборка gcc у вас стоит. В последнее время оно собирается как arm-none-eabi-, раньше модно было делать arm-elf-, бывают еще разные arm-linux-eabi-.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.