реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Странное поведение EWAVR 4.21A, Возникновение ошибки при объявлении структуры
Baser
сообщение Feb 28 2008, 21:59
Сообщение #1


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Вдруг начала возникать ошибка на пустом месте, когда пытаюсь объявить структуру в одном си файле, объявление extern в хедер файле, а применить эту структуру в третьем си файле:
Код
Error[Pe147]: declaration is incompatible with "struct <unnamed> __near GSM_Rx" (declared at line 27 of "C:\My_Jobs\ C:\My_Jobs\VB1\gsm.c 13

Причем ошибка пропадает, если заменить структуру на отдельные char или передвинуть эти объявления в другие файлы sad.gif

Что это может быть? Час потратил, передвигая структуру с места на место - никакой закономерности не обнаружил, то она есть, то нет wacko.gif

Кому не лень, посмотрите у себя, может на другой версии этого глюка нет?
Обкоцанный (но с ошибкой) проект прилагаю. От машины не зависит: и на работе, и дома одинаково.
Ошибка возникает в файле gsm.c на структуре GSM_Rx
Прикрепленные файлы
Прикрепленный файл  VB1.zip ( 15.88 килобайт ) Кол-во скачиваний: 65
 
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 28 2008, 22:55
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Baser @ Feb 29 2008, 00:59) *
Вдруг ...

Это не вдруг sad.gif
Прикрепленные файлы
Прикрепленный файл  gsm.rar ( 1.42 килобайт ) Кол-во скачиваний: 82
 


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 28 2008, 23:12
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Объявления лучше делать именно в том модуле, где переменные/структуры инициализируются/используются. В остальных модулях их нужно просто externнить.
Исходники просмотрел "по диагонали". Замечание такое. Пользуйтесь активнее условной компиляцией. Например, если бы вы содержимое хедера gsm.h обрамили так
Код
#ifndef GSM_H
...
...
...
#endif

То было бы проще externить эту структуру. Достаточно проincludeть gsm.h непосредственно уже в исходник.
К тому же я обычно пользуюсь typedefом, в т.ч. для того, чтобы было удобнее объявлять и externить структуры.
Ведь проще один раз написать
Код
#ifndef GSM_H
typedef struct st_GSM_Rx {
  unsigned char Buf[80];
  unsigned char Start;
  unsigned char End;
  unsigned char Tout;
  } st_GSM_Rx;
#endif

А потом проincludeть этот хедер и знай объявляй себе эти структуры
Код
st_GSM_Rx GSM_Rx;

и/или
Код
extern st_GSM_Rx GSM_Rx;


P.S. гы smile.gif пока я писал ответ, zltigo уже пример с конкретными изменениями предложил.
Go to the top of the page
 
+Quote Post
Baser
сообщение Feb 29 2008, 09:32
Сообщение #4


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(zltigo @ Feb 29 2008, 00:55) *
Это не вдруг sad.gif
Все-таки, предложеный вами typedef - это не решение вопроса, а обходной путь. Через typedef все работает. Я вообще typedef применяю только тогда, когда нужно структуру применить несколько раз. В случае уникальной структуры предпочитаю явные определения. Иначе, для того, чтобы посмотреть на члены структуры, приходится лезть лишний раз в хедер. Зачем мне лишняя вложенность, только ухудшает понимабельность. А в этом конкретном случае я решил свести несколько отдельных char в структуру только исходя из эстетических соображений smile.gif По стандарту Си мой вариант написания совершенно легален.

Цитата(rezident @ Feb 29 2008, 01:12) *
...Пользуйтесь активнее условной компиляцией...
Это дельное замечание, буду применять. Раньше писал небольшие проекты, ограничивался несколькими файлами в проекте: main.c; modules.c; isr.c; memory.c; defines.h - все было без проблем. Сейчас проект побольше. А когда в файле больше нескольких тысяч строк, уже неудобно, решил начать делить проект ещё и по периферии. Вот и возникла по-первости такая каша smile.gif

to All: Спасибо за участие, с вашей помощью разобрался, дело в следующем. ИАР не всегда дозволяет в одном модуле наличие собственно определения переменной и определение её как extern. Примеры:

Это проходит без ошибок:
Код
extern char a;
extern int b[10];
char a;
int b[10];

typedef struct c_t{
    char a;
    int  b;
    } c_t;
extern c_t ccc;
c_t ccc;
extern c_t ccc;


А на явное определение struct или union ругается:
Код
struct {
    char a;
    int  b;
    } ddd;
extern struct {
    char a;
    int  b;
    } ddd;


И я не знаю, правильно это или нет. По моему мнению все должно быть однообразно, а не так sad.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 29 2008, 10:02
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Baser @ Feb 29 2008, 12:32) *
Все-таки, предложеный вами typedef - это не решение вопроса, а обходной путь.

Можно и без typedef, это совершенно не принципиально (см. приложение). Но
1. структуры надо описывать просто, однозначно и в одном месте.
2. нет ни одной причины не использовать typedef везде, где это возможно.
Цитата
Иначе, для того, чтобы посмотреть на члены структуры, приходится лезть лишний раз в хедер.

Проблема в том, что просто нужно использовать нормальные текстовые редакторы, как минимум поддерживающие тэги - решает массу проблем со стилем написания и навигацией, а не только с просмотром структур.
Цитата
И я не знаю, правильно это или нет.

Правильно.
Прикрепленные файлы
Прикрепленный файл  gsm_s.rar ( 1.22 килобайт ) Кол-во скачиваний: 59
 


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Baser
сообщение Feb 29 2008, 12:32
Сообщение #6


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(zltigo @ Feb 29 2008, 12:02) *
... 2. нет ни одной причины не использовать typedef везде, где это возможно.
Ну почему же, или причина которую я привел не причина? smile.gif

Цитата
... нужно использовать нормальные текстовые редакторы...
Дело вкуса и привычки (и главное, лени smile.gif )

Код
struct GSM_Rx_s {
  unsigned char Buf[80];
  unsigned char Start;
  ...
  };
extern struct GSM_Rx_s GSM_Rx;
struct GSM_Rx_s GSM_Rx;

Такое тоже применяю, мне такая форма нравится даже больше, чем typedef

Цитата
Правильно.
А вот если бы вы объяснили почему, или привели ссылку на страницу стандарта - было бы просто замечательно. В таких вещах верить нА слово не привык.
Вот мне все-таки кажется, что компилятор должен был бы ругаться во всех вышеприведенных мною примерах, т.к. объявление в одном модуле переменной и как глобальной и как внешней больше похоже на ошибку.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 29 2008, 12:46
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Baser @ Feb 29 2008, 15:32) *
объявление в одном модуле переменной и как глобальной и как внешней больше похоже на ошибку.

Нет - обычный разумный подход делу, поскольку ругань в таком случае исключает нормальное использование header-ов в файлах, где собственно переменные объявлены. Ни к каким ошибкам это привести не может, поскольку если "снаружи" вдруг еще такая переменная существует, то на это 100% выругается линкер.
Цитата
Ну почему же, или причина которую я привел не причина?

Причина ну никак не относится к использованию или неиспользованию typedef. Или я чего-то совсем не понимаю.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Baser
сообщение Feb 29 2008, 13:49
Сообщение #8


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(zltigo @ Feb 29 2008, 14:46) *
Причина ну никак не относится к использованию или неиспользованию typedef. Или я чего-то совсем не понимаю.
Да, похоже мы одни и те же слова воспринимаем по-разному. Я имею ввиду след: если стандарт в конкретном случае разрешает не применять typedef и я считаю, что так будет наглядней, то нет никаких причин его использовать. Короче, тоже дело вкуса, спорить не о чем smile.gif

Цитата
Нет - обычный разумный подход делу, поскольку ругань в таком случае исключает нормальное использование header-ов в файлах, где собственно переменные объявлены. Ни к каким ошибкам это привести не может, поскольку если "снаружи" вдруг еще такая переменная существует, то на это 100% выругается линкер.
Со всем этим согласен. Но почему тогда это недопустимо по отношению к структурам, описанным в явном виде:
Код
extern struct {
    char a;
    int  b;
    } ddd;
struct {
    char a;
    int  b;
    } ddd;
Error[Pe147]: declaration is incompatible with "struct <unnamed> __near ddd"

Я не вижу логики в действиях компилятора. Или он начинает и в случае extern выделять память?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 29 2008, 14:25
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Baser @ Feb 29 2008, 16:49) *
Я имею ввиду след: если стандарт в конкретном случае разрешает не применять...
...
Короче, тоже дело вкуса, спорить не о чем smile.gif

Стандарт языка позволяет многое чего не применять, он даже совершенно спокойно позволяет делать массу ошибок smile.gif, но при этом дает некоторые средства для контроля над типами уменьшающие вероятность потенциальных ошибок. Пользоваться или нет - это не "дело вкуса", это показатель уровня владения инструментом. На рояле я тоже могу чего-нибудь настучать одним пальцем - он мне это вполне позволит, только рассуждать о вкусах я при этом не буду smile.gif
Цитата
Я не вижу логики в действиях компилятора. Или он начинает и в случае extern выделять память?

Для начала я не вижу логики в действиях программиста дважды определившего одну и ту-же структуру. Дальнейшие логические построения, рассуждения и толкования должен-ли 'extern' служить решающим указанием компилятору для того, что-бы считать это нагромождение разумным, меня с практической точки зрения совершенно не интересуют. Однако, поведение любого компилятора молча глотающего подобные выражения сочту совершенно неправильным.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Baser
сообщение Feb 29 2008, 16:06
Сообщение #10


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(zltigo @ Feb 29 2008, 16:25) *
Для начала я не вижу логики в действиях программиста дважды определившего одну и ту-же структуру...
Однако, поведение любого компилятора молча глотающего подобные выражения сочту совершенно неправильным.
Не надо так сразу кипятится smile.gif , я же разобраться хочу, а не просто так по клавишам стучу. Очень часто простейшие мысли в голову почему-то сразу не приходит. Теперь дошло, действительно удобнее только один раз описывать. Но компилятор, ИМХО, мог бы ограничится предупреждением, поскольку структуры идентичны.

Цитата
... но при этом дает некоторые средства для контроля над типами уменьшающие вероятность потенциальных ошибок...
Насчет контроля типов тут много копей сломано. Но я в этом вопросе так и не разобрался. Вот вы говорили:
Цитата
#define и typedef по разному обрабатываются - один препроцессором, а второй компилятором. Компилятор (или дополнительные утилиты типа lint) могут дополнительно заниматься котролем типов, а препроцессор - нет.
Тут хотя случай без #define, но похоже. Чем все-таки будет отличаться обработка структур CCC и DDD? И там и там структура, и там и там ее обрабатывает компилятор:
Код
typedef struct cc {
    char a;
    int  b;
    } ccc_t;
ccc_t CCC;

struct dd {
    char a;
    int  b;
    } DDD;
Кстати, если бы был #define, то после него все равно явное описание типа обрабатывалось бы компилятором.

Вот Сергей Борщ в том обсуждении сказал: "Поэтому надо больше читать тематической литературы. Разница есть."
А я никак не могу найти ту "техническую литературу", где этот вопрос освящен. Например у Кернигана и Ричи (2-е изд) применение typedef никак не связывается с улучшенным (добавочным) контролем типов:
Цитата
Следует подчеркнуть, что объявление typedef не создает объявления нового типа, оно лишь сообщает новое имя уже существующему типу. Никакого нового смысла эти новые имена не несут, они объявляют переменные в точности с теми же свойствами, как если бы те были объявлены напрямую без переименования типа. Фактически typedef аналогичен #define с тем лишь отличием, что при интерпретации компилятором он может справиться с такой текстовой подстановкой, которая не может быть обработана препроцессором...
Помимо просто эстетических соображений, для применения typedef существуют две важные причины. Первая - параметризация программы, связанная с проблемой переносимости...
Вторая причина, побуждающая к применению typedef,- желание сделать более ясным текст программы...

И все... Так где об этом можно почитать? Гуру, дайте ссылку rolleyes.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 29 2008, 16:50
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Baser @ Feb 29 2008, 19:06) *
Не надо так сразу кипятится smile.gif

Ооооо! Кипячусь совсем не так smile.gif. В данном случае я совершенно спокоен, не спокоен, я буду, например, тогда, когда мой заказчик потребует не пользоваться typedef smile.gif
Цитата
Чем все-таки будет отличаться обработка структур CCC и DDD? И там и там структура

Две совсем разные вещи! В одном случае это определение структуры а во втором создание структуры во время ее определения - так сказать заплатка для краткости и выразительности. В случае локальной/статической структуры - позволяет с минимальными количеством ударов по клавишам описать и создать локальную структуру. Сам пользуюсь, при этом сам внешний вид при чтении подчеркивает ограниченность применения такой структуры. Попытки описания в таком стиле глобально доступных структур просто банально неудобны, поскольку требуют дважды дублировать описание структуры - при ее создании и при обращении к структуре за пределами объекта компиляции. Посему сетовать на компилятор, который не желает понимать, что добавлением extern Вы хотите не создать структуру, а только ее описать, я совершенно не собираюсь. Кстати, повторю, использование typedef не принципиально (пример приводил).
Цитата
Так где об этом можно почитать? Гуру, дайте ссылку

Наверное, я дурак sad.gif - я много учился на своих, а не на чужих ошибках sad.gif. Посему ссылок у меня нет. Чувство языка есть, писать могу, а ссылок нет smile.gif. Книгу, что-ли написать? smile.gif и ссылаться. Единственно, что меня несколько оправдывает, так это то, что на момент достижения мною приличного уровня программирования Интернета, считайте еще не было sad.gif. Диалап по модему 2400/NONE на LatNet, по знакомству, с возможностью (чудо!) поползать по FTP это уже позже - год 91-92....

P.S.
Кстати, попробовал четыре наиболее используемых мной компилятора, рад сообщить, что мое мнение совпало с мнением их создателей smile.gif.

Сообщение отредактировал zltigo - Feb 29 2008, 19:24


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
rezident
сообщение Feb 29 2008, 21:12
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Baser @ Feb 29 2008, 21:06) *
И все... Так где об этом можно почитать? Гуру, дайте ссылку rolleyes.gif

Прикрепленные файлы
Прикрепленный файл  Recommended_C_Style_and_Coding_Standards.pdf ( 129.86 килобайт ) Кол-во скачиваний: 105
Прикрепленный файл  C_Coding_Standard_an2000.pdf ( 371.54 килобайт ) Кол-во скачиваний: 114
 
Go to the top of the page
 
+Quote Post
Baser
сообщение Feb 29 2008, 21:16
Сообщение #13


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(zltigo @ Feb 29 2008, 18:50) *
Кстати, повторю, использование typedef не принципиально (пример приводил).
Вопрос, вынесенный мною в тему топика, я уже для себя прояснил, спасибо. Просто мне показалось, что вы раньше делали упор на то, что применение typedef при определении структур улучшает именно контроль типов, а не удобство использования структуры. Если я не прав, поправьте меня.

Сейчас у меня в процессе разговора на первый план вышел другой вопрос, который я пытался задать в предыдущем посте, но видимо неудачно. Это тот старый вопрос с #define. Вот он еще раз (о ужас 05.gif ):
Цитата
не вижу принципиальной разницы между:
typedef unsigned char uint8;
и
#define uint8 unsigned char

В чем же все-таки проявляется эта разница в плане контроля типов? Разве в случае с #define, после работы препроцессора не происходит такая-же обработка компилятором? А то получается, что контроль типов производится только при наличии typedef. И объявление:
Код
typedef unsigned char uint8;
uint8 foo;

лучше, чем (после препроцессора):
Код
unsigned char foo;


Пока что я слышал от всех только общие рассуждения: "#define и typedef по разному обрабатываются ", "Дурной стиль без всякой на то надобности да и еще с побочными эффектами" и т.д. Но никто не дал ссылку или разъяснил почему это так в деталях.
Поделитесь, pls, своими знаниями, своим опытом. Приведите хоть один пример, где это дает ошибку. А то я уже запуган 05.gif , озираюсь в поисках опасностей, но нигде их не вижу.
Я ответ не знаю, и пока не могу найти ответ на него в первоисточниках, вот и хочу порасспрашивать знающих людей. Думаю, это еще многих может просветить.


p.s. Кстати, у вас были намного лучшие условия в плане интернета: я периодический доступ (пару раз в неделю на пару часов) получил только году в 98, а постоянный доступ на работе (с жуткими ограничениями) только в конце 2000 sad.gif
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 29 2008, 21:50
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Baser @ Mar 1 2008, 00:16) *
что применение typedef при определении структур улучшает именно контроль типов, а не удобство использования структуры.

И то и другое.
lint не приходилось в помощь компилятору использовать? misra?
Цитата
Приведите хоть один пример, где это дает ошибку
....
озираюсь в поисках опасностей, но нигде их не вижу.

Там, откуда меня цитировали, примера разве не было? Посмотрите сточкой ниже. Для тех, кто не понял, разъяснения там-же несколькими постами ниже есть.

От Вас жду хоть один пример "вредности" typedef.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Baser
сообщение Feb 29 2008, 22:35
Сообщение #15


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Ну, хорошо, будем считать, что я удовлетворился, все равно нюансов от вас не добьешся cool.gif

Про lint и misra слышал, но не применял, видимо поэтому у меня и возникают все эти вопросы. Хотя, как я понимаю, это больше нужно для переносимости кода а не для контроля типов.

Пример с #define, наконец разобрал. Там это как-то неочевидно расписано. Мне нужно подробно, как для тупого студента biggrin.gif Да, действительно, в частных случаях возможны ошибки.

Про "вредность" typedef я не говорил, я говорил только о снижении читабельности кода при сокрытии определений структур за typedef. Больше у меня к этому оператору претензий нет. Но это вопрос пристрастий.

to rezident: просмотрел ваши документы, но нужного мне не нашел. Это хорошие наставления по стилю правописания на Си, а я хотел почитать более углубленно про применение typedef и его влияние на улучшение ситуации с контролем типов.

Всем спасибо, прошу и других высказать свое мнение и привести реальные примеры, а то похоже наш модератор задавил остальных своим автортиетом biggrin.gif beer.gif
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 20:06
Рейтинг@Mail.ru


Страница сгенерированна за 0.01537 секунд с 7
ELECTRONIX ©2004-2016