Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Странное поведение EWAVR 4.21A
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Baser
Вдруг начала возникать ошибка на пустом месте, когда пытаюсь объявить структуру в одном си файле, объявление 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
zltigo
Цитата(Baser @ Feb 29 2008, 00:59) *
Вдруг ...

Это не вдруг sad.gif
rezident
Объявления лучше делать именно в том модуле, где переменные/структуры инициализируются/используются. В остальных модулях их нужно просто 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 уже пример с конкретными изменениями предложил.
Baser
Цитата(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
zltigo
Цитата(Baser @ Feb 29 2008, 12:32) *
Все-таки, предложеный вами typedef - это не решение вопроса, а обходной путь.

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

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

Правильно.
Baser
Цитата(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

Цитата
Правильно.
А вот если бы вы объяснили почему, или привели ссылку на страницу стандарта - было бы просто замечательно. В таких вещах верить нА слово не привык.
Вот мне все-таки кажется, что компилятор должен был бы ругаться во всех вышеприведенных мною примерах, т.к. объявление в одном модуле переменной и как глобальной и как внешней больше похоже на ошибку.
zltigo
Цитата(Baser @ Feb 29 2008, 15:32) *
объявление в одном модуле переменной и как глобальной и как внешней больше похоже на ошибку.

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

Причина ну никак не относится к использованию или неиспользованию typedef. Или я чего-то совсем не понимаю.
Baser
Цитата(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 выделять память?
zltigo
Цитата(Baser @ Feb 29 2008, 16:49) *
Я имею ввиду след: если стандарт в конкретном случае разрешает не применять...
...
Короче, тоже дело вкуса, спорить не о чем smile.gif

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

Для начала я не вижу логики в действиях программиста дважды определившего одну и ту-же структуру. Дальнейшие логические построения, рассуждения и толкования должен-ли 'extern' служить решающим указанием компилятору для того, что-бы считать это нагромождение разумным, меня с практической точки зрения совершенно не интересуют. Однако, поведение любого компилятора молча глотающего подобные выражения сочту совершенно неправильным.
Baser
Цитата(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
zltigo
Цитата(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.
rezident
Цитата(Baser @ Feb 29 2008, 21:06) *
И все... Так где об этом можно почитать? Гуру, дайте ссылку rolleyes.gif
Baser
Цитата(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
zltigo
Цитата(Baser @ Mar 1 2008, 00:16) *
что применение typedef при определении структур улучшает именно контроль типов, а не удобство использования структуры.

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

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

От Вас жду хоть один пример "вредности" typedef.
Baser
Ну, хорошо, будем считать, что я удовлетворился, все равно нюансов от вас не добьешся cool.gif

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

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

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

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

Всем спасибо, прошу и других высказать свое мнение и привести реальные примеры, а то похоже наш модератор задавил остальных своим автортиетом biggrin.gif beer.gif
zltigo
Цитата(Baser @ Mar 1 2008, 01:35) *
... похоже наш модератор задавил остальных своим автортиетом biggrin.gif beer.gif

Это не я! Невиноватый я! Честное слово, это не я придумал typedef smile.gif!!! Это отцы основатели ввели такую ненужную штуку и так задавили все последующие комитеты по С и С++ своим, понимаешь, авторитетом, что эти комитеты до сих пор этот пережиток прошлого "снижающий читабельность кода" не запретили. Может голосование устроим в поддержку отмены? smile.gif
Нежели еще примеры нужны, то подсказываю - области видимости typedef можно ограничить, а #define - нет - ну не разбирается препроцессор в языковых структурах...
А как насчет:
typedef unsigned char xbuff_t[X_SIZE];

Цитата(Baser @ Mar 1 2008, 01:35) *
Про lint и misra слышал, но не применял, видимо поэтому у меня и возникают все эти вопросы. Хотя, как я понимаю, это больше нужно для переносимости кода а не для контроля типов.

Не сколько для портируемости, сколько для много более жесткого контроля исходного текста с точки зрения возможных недопониманий компиляторами. Для серьезных применений достаточно часто требуют, хотя та-же MISRA это полный мрак sad.gif. Хотя для общего представления рекомендую разок прогнать.

Цитата(Baser @ Mar 1 2008, 01:35) *
я говорил только о снижении читабельности кода при сокрытии определений структур за typedef.

Ну не скрывает сам typedef никакие определения структур. Совсем не скрывает. Третий раз повторяю - посмотрите второй пример правки Вашего исходника - ну нет там уже никаких typedef, а структуры по Вашему утверждению "cкрыты".
Baser
Цитата(zltigo @ Mar 1 2008, 01:12) *
А как насчет:
typedef unsigned char xbuff_t[X_SIZE];

Любите вы загадки задавать! Конечно, такое определение типа при помощи #define не слепить.
Но я мыслю попроще, и это как раз тот пример, как я не буду писать, потому что:
"снижается читабельность кода при сокрытии определений реальных объектов за typedef" (ИМХО)
Я предпочитаю написать в пять раз длиннее, но понятней для меня. А чтобы понять ваш пример, мне пришлось голову поломать. Смысл я понял, но необходимость в такой записи - нет. Тупой прямой код понятней и ошибки точно так же выявляет:
Код
#define X_SIZE  2
typedef unsigned char xbuff_t[X_SIZE];
xbuff_t bufA[3];

unsigned char bufB[3][X_SIZE];

void foo(void)
  {
  bufA[1][1] = 55;
  bufA[1][2] = 66;  // Warning[Pe175]: subscript out of range
  
  bufB[1][1] = 77;
  bufB[1][2] = 88;  // Warning[Pe175]: subscript out of range
  }
Удивило, а почему предупреждение, а не ошибка?

Впрочем, о чем это я cool.gif : "На вкус и цвет товарища нет".
zltigo
Цитата(Baser @ Mar 1 2008, 17:21) *
... и ошибки точно так же выявляет:

Попробуйте под разными компиляторами (и под C++), попробуйте как это будет работать когда все разнесено по разным файлам. Попробуйте оценить "удобство" "прямого" кода, кода в одном файле
Вы написали:
unsigned char bufB[3];
а в другом соответственно:
extern unsigned char bufB[3]; - удобно за собой эту троечку таскать? Даже если она через #define где-то там в третьем месте определена? А ошибиться написав extern unsigned char bufB[5], или bufB[Y_SIZE] вместо X_SIZE?
Цитата
..но понятней для меня.

Так понятия наши меняются со временем. Полагаю, что Вы не родились с врожденным пониманием арифметики, но абсолютно уверен, что потом "поняли" и на данный момент никаких проблем не испытываете smile.gif.

P.S.
Подкинуть еще "загадок" про typedef?
Можно и к понимабельности перейти, например, хотелось-бы увидеть, как выглядит прототип такой функции:
Код
typedef void (*func)(int);
func foo( int data, func a );

в более понятной для Вас форме.
Baser
Вы неправильно поняли мои возражения против typedef и проэкстраполировали их на те области, про которые я не говорил. Я уже получаюсь какой-то ярый противник typedef smile.gif Если вы вернетесь к началу топика, то там я говорил только о простейших случаях определения структур и юнионов (причем применяющихся однократно).

Цитата(zltigo @ Mar 1 2008, 19:34) *
Можно и к понимабельности перейти, например, хотелось-бы увидеть, как выглядит прототип такой функции в более понятной для Вас форме.
Код
typedef void (*func)(int);
func foo( int data, func a );

Тут вы вообще подкинули пример из учебников для иллюстрации того, для чего этот оператор именно и нужен. Конечно, можно написать "тупо-прямо" и конечно это будет нечитабельно. Никто и не спорит:
Код
void (*foo(int data, void(*a)(int)))(int);


На тему применения различных приемов программирования можно пофилософствовать. По моему скромному разумению все более-менее сложные приемы можно прочувствовать только на практике. Пока я пишу маленькие проектики не превышающие несколько десятков Кслов кода (в самом крайнем случае), мне особо незачем переходить на высокие уровни абстракции в описаниях объектов. Достаточно примитивного начального уровня. Да и до конца понять и прочувствовать эти "высокие уровни" вряд-ли удасться. Поскольку реальной необходимости нет. А вот когда жизнь заставит, когда будет действительно большой проект, тогда это понимание само и придет (разумеется только при наличии базовых знаний biggrin.gif ).
zltigo
Цитата(Baser @ Mar 2 2008, 00:33) *
Если вы вернетесь к началу топика, то там я говорил только о простейших случаях определения структур и юнионов (причем применяющихся однократно).

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

Учебников давно не читал sad.gif sad.gif sad.gif, все больше "опыт" sad.gif, так-что кусочек из реального исходника.
Цитата
...тогда это понимание само и придет.

И больно стукнет прямо в лоб sad.gif. Лучше заранее подготовится smile.gif пока все просто smile.gif.
Да и в простых вещах, например, при дополнении атрибутами const, volatile можно нарваться на совсем ненужные сюрпризы.
Baser
Да, наверное, вы как всегда правы wink.gif

Цитата(zltigo @ Mar 2 2008, 00:43) *
И больно стукнет прямо в лоб sad.gif. Лучше заранее подготовится smile.gif пока все просто smile.gif.

Дык я об этом и пишу, только в более мягкой форме. И еще: зачем же я все эти разговоры завел? Получил бы ответ на свой первоначальный вопрос - и шмыг в свою норку - дальше копать, не разбираясь, а может я копаю не так или не туда biggrin.gif Я вот и пытаюсь "заранее подготовится пока все просто" и можно это сделать "мимоходом", с минимумом трудозатрат и максимумом пользы cool.gif

Цитата
Да и в простых вещах, например, при дополнении атрибутами const, volatile можно нарваться на совсем ненужные сюрпризы.

Если не трудно, не ради "разговор поддержать", а ради "заранее подготовится", можете привести примеры проблем или кратко описать их?
zltigo
Цитата(Baser @ Mar 2 2008, 15:47) *
Да, наверное, вы как всегда правы wink.gif

Я не стадаю манией величия, посему прав далеко не всегда, правда "выступать" стараюсь в случаях, когда есть уверенность близкая к абсолютной smile.gif.
Цитата
..зачем же я все эти разговоры завел?

Дык, зачем-же я все эти разговоры продолжаю smile.gif - чувствую, что "лед тронулся" smile.gif. Есть и еще тайный умысел - может когда поработать вместе придется smile.gif.
Цитата
..можете привести примеры проблем или кратко описать их?

Можно, вот иллюстрация к помянутому:
Код
typedef unsigned char* bufptr_t;
#define bufptr_d char*

const bufptr_b a;
bufptr_b const b;
const bufptr_t c;
bufptr_t const d;

Только ведь все эти "семь бед" имеют одно радикальное решение smile.gif. Я просто всех гараблей не перечислю - в свое время хватило единожды наступить, дабы перейти раз и навсегда, и выбрость разом все эти проблемы из головы. В чужих исходниках, правда, встречать приходится sad.gif, что не дает совсем забыть sad.gif.
Baser
Цитата(zltigo @ Mar 2 2008, 15:02) *
Можно, вот иллюстрация к помянутому:

ОК, понятно. Это когда от перестановки слагаемых начинает меняться сумма sad.gif
MALLOY2
По ходу вопрос, может я и гоню....

Не получается обьявить тип структуры в которой этот тип и используется.

Код
typedef struct
{
   blc_t next;
   int err;
   int state;
}blc_t;


Error[Pe020]: identifier "blc_t" is undefined
Сергей Борщ
Так сделать невозможно - какой размер будет иметь структура, если она вмещает саму себя? Рекурсия-с!
А если указатель на эту структуру, то так:
Код
typedef struct blc_t
{
   blc_t *next;
   int err;
   int state;
}blc_t;
Baser
Цитата(MALLOY2 @ Mar 4 2008, 16:48) *
Не получается обьявить тип структуры в которой этот тип и используется.

Ну, во-первых, вы пытаетесь применить тип, который вы еще не объявили (только находитесь в процессе объявления).

А во-вторых, даже если бы вам компилятор это разрешил делать, у вас получилась бы рекурсия. Подумайте, что при этом получится: бесконечная вложенность, фракталы. Боюсь, вам памяти не хватит biggrin.gif
MALLOY2
Сорри это я опечатался естественно там указатель.

Код
typedef struct blc_t
{
   blc_t *next;
   int err;
   int state;
}blc_t;


Не работает.


Код
struct blc_t
{
   struct blc_t *next;
   int err;
   int state;
}blc_t;


так работает
zltigo
Цитата(MALLOY2 @ Mar 4 2008, 18:13) *
Код
typedef struct blc_t
{
   blc_t *next;
   int err;
   int state;
}blc_t;


Не работает.

Какие проблемы? Естественно нельзя использовать тип, до его определения, но проблем-то и нет:
Код
typedef struct blc_s
{
   struct blc_s *next;
   int err;
   int state;
}blc_t;
MALLOY2
Спс, помогло smile.gif
zltigo
Цитата(Baser @ Mar 4 2008, 18:11) *
...бесконечная вложенность, фракталы. Боюсь, вам памяти не хватит biggrin.gif

Совершенно обыденный прием, например, менеджер памяти - Меmory Control Block содержит указатели на аналогичные блоки в цепочке.
Код
// Memory Control Block (MCB)
typedef struct heap_mcb
{
    struct heap_mcb *next;  
    struct heap_mcb *prev;       
    union type_size ts;          
    union mark_owner ow;        
} heap_mcb;
Сергей Борщ
Цитата(MALLOY2 @ Mar 4 2008, 17:13) *
Код
typedef struct blc_t
{
   blc_t *next;
   int err;
   int state;
}blc_t;


Не работает.
Проверял в C++ (GCC 4.1.2) - там работало. Для С наверное надо делать так:
Код
struct blc_t;
typedef struct
{
   struct blc_t *next;
   int err;
   int state;
}blc_t;
или как написал zltigo
Цитата(zltigo @ Mar 4 2008, 18:28) *
Совершенно обыденный прием, например, менеджер памяти - Меmory Control Block содержит указатели на аналогичные блоки в цепочке.
Указатели - да. Получаем связанные списки. В исходном вопросе внутри структуры была сама эта же структура smile.gif
chernenko
Чтобы не плодить темы решил написать здесь.
Подскажите пожалуйста, вроде Си позволяет описать структуру и объявить указатель на эту структуру

например
Код
struct
{
  bool ErrAlready;  
  bool ErrUnknown;

} *pFlag;


И затем обращаться к членам структуры как
Код
pFlag->ErrAlready = true;
pFlag->ErrUnknown = false;



Но в результате присваивание происходит не корректно.

Если делать использовать

Код
struct
{
  bool ErrAlready;  
  bool ErrUnknown;
} Flag;


И затем обращаться к членам структуры как
Код
Flag.ErrAlready = true;
Flag.ErrUnknown = false;


То все нормально...

Что я делаю не так?
Сергей Борщ
Цитата(chernenko @ Oct 1 2008, 15:45) *
Что я делаю не так?
Забыли выделить память под структуру и присвоить указателю адрес выделенного участка? Покажите инициализацию pFlag.
chernenko
Цитата(Сергей Борщ @ Oct 1 2008, 17:09) *
Забыли выделить память под структуру и присвоить указателю адрес выделенного участка? Покажите инициализацию pFlag.


Вот двеструктуры:

struct TErr
{
volatile bool Already;
volatile bool Unknown;
};
struct TErr* pErr;

struct TFlag
{
volatile bool No;
volatile bool Ok;
};
struct TFlag* pFlag;


Стоит изменить один элемент структуры, то происходит изменение элемента в другой структуре
IgorKossak
Ну у Вас опять же выделено место только под указатели на структуры, а сами структуры где?
Надо примерно так:
Код
struct TErr
{
    bool Already;
    bool Unknown;
};
struct TErr Err;
struct TErr* pErr = &Err;

struct TFlag
{
    bool No;
    bool Ok;
};
struct TFlag Flag;
struct TFlag* pFlag = &Flag;

В таком случае Вы создаёте место под сами структуры и их адреса передаёте указателям.
В Вашем предыдущем случае указатели были проинициализированы нулями по умолчанию и указывали на одно и то же место.
chernenko
IgorKossak,

Да, точно. Глюканул. Всё работает.

Код
struct TErr
{
    bool Already;
    bool Unknown;
}  Err;
TErr* pErr = &Err;

struct TFlag
{
    bool No;
    bool Ok;
}Flag;
TFlag* pFlag = &Flag;
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.