Отговори на тема  [ 10 мнения ] 
Структури в AvrGCC (-std=gnu99) 
Автор Съобщение
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Съб Сеп 25, 2004 10:32 pm
Мнения: 710
Мнение Структури в AvrGCC (-std=gnu99)
(Последните 2-3 дни задръстих с лични съобщения колега от форума с подобни въпроси. Благодарение на неговата любезност и търпение до голяма степен ми се изясни концепцията на C дефинирането на данни и функции, но за основа ползвам проект, който не отговаря на книгите, затова, моля пояснете :))

Потърсих пояснения, но са различно описани в 2.5 книги, които имам, в електронните книги, които съм изтеглил, по форумите, в които питах :)
А е още по-странно в проекта, който ползвам (от един германец - FAT16/FAT32 система за SD MMC карти за ATMega - най-долу съм дал линк и сорсове).

Вероятно е елементарно, начинаещ съм в C и не ми стана ясно,.

Става дума за дефиниране на структури.
Въпросите са следните:

1. Каква е разликата между дефинициите без typedef (a) и с typedef, като с typedef има поне два начина (b) и (c):
a)
Код:
struct blabla{
  int X;
  int Y;
};
b)
Код:
typedef struct blaXXX{
  int X;
  int Y;
} blabla;
c)
Код:
typedef struct{
  int X;
  int Y;
} blabla;



Едната разлика е, че типа след typedef може да се ползва по-късно, но немецът е ползвал типа и без typedef
Спокойно си дефинира по (a) и след това пише:
Код:
struct blabla*z;

и си ползва z катo структура (например z->x).

2. Немецът си е декларирал структурите в fat.c (без typedef - както е в 1(а)), но, за да са му достъпни в fat.h (където са хедърите на функциите, които ползват структурите) е добавил дублиране на дефинициите от вида:
Код:
struct blabla;

Това е ОК и неговият пример върви, но в трети файл (например main.c), където са #include fat.h се получава грешки при ползване на полета от така дефинираните структури.
Но, ако структурите се предват към fat.c като параметри на функции - няма проблеми.

Вероятно ще кажете, че стила на дефиниране на структури без typedef не е добър, но така го е решил човека и аз трябва да се оправям


Това е сайта с оригинала
По-долу атачвам същия оригинал с добавени проектни файлове за AvrStudio4 и AvrStudio5, както и работеща симулация за Протеус (вкл 100МБ MMC карта - в RAR не заема място :) - за да тръгне - може да се наложи да се уточнят пътища в симулацията - до hex файла и до файла с съдържанието на MMC картата)


Прикачени файлове:
Пон Мар 14, 2011 11:34 pm
Профил ICQ WWW
Ранг: Ориентиран
Ранг: Ориентиран

Регистриран на: Вто Фев 06, 2007 2:45 am
Мнения: 263
Мнение 
Разлика в случая няма.
Начина, по който го е написал шваба е добър пример за мърлящина и предпоставка за полагане по вратЪТ.
Правилото е: дори да декларираш една-единствена променлива от къстъм тип - направи си тип. Евентуално ако ти дотрябва после за навън - само го слагаш в .h файла и готово. Конкретно от примера ти - 1 с) е културния начин. За четимост може да добавиш един префикс "t_", "T" или суфикс "_t", да се различава типа от раз.


Вто Мар 15, 2011 12:17 am
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Съб Сеп 25, 2004 10:32 pm
Мнения: 710
Мнение Как се предава адрес на указател на структура към функция?
СЛЕДВАЩ въпрос

Как се предава адрес на указател на структура към функция?
Ако някоя функция трябва да смени адреса на структурата (да създаде нова структура и да я върне вместо старата) как се прави?

За сега заобикалям проблема, като правя функцията с типа, който ми трябва, но не ми харесва.
(Явно книжките ми са доста тънки и подобни хватки са прескочени, вероятно, защото са елементарни за мислещите на C :))

Сега ползвам нещо такова:
Код:
struct tBlaBla* change_BlaBla( struct tBlaBla* aBlaBla){
...
return xBlaBla; // не е aBlaBla :), a e xBlaBla
}

и ползвам функцията така
Код:
zBlaBla=change_BlaBla(BlaBla);
if (zBlaBla){
BlaBla=zBlaBla;
}


Ако знам как да предам адреса на структурата, функцията ми може да е void :)
(Гледам, адреси на променливи се предват с &, например int&, но не успях да налучкам синтаксиса за указатели към структури)


Вто Мар 15, 2011 9:41 pm
Профил ICQ WWW
Ранг: Новодошъл
Ранг: Новодошъл

Регистриран на: Чет Окт 02, 2008 10:24 pm
Мнения: 105
Мнение 
със указател към указател към структура.
А функцията как ще създаде нова структура не е ясно.
Ако структурата е локална , след излизане от скопа на функцията , този указател който ще се върне ще сочи някъде си.

Ако ползваш указател към указател към структура, то можеш да го пренасочиш, но към предварително декларирана
структура , а не към създадена от функцията.
Другото за което се сещам е да се върне адрес от памметта , кастван до указател към структура,
но на този адрес паметта, трябва да се знае че е заделен за структура от този тип.


Вто Мар 15, 2011 9:58 pm
Профил ICQ
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Съб Сеп 25, 2004 10:32 pm
Мнения: 710
Мнение 
На това "указател към указател" ми се губи синтаксиса. Вероятно трябва да се задава явно (с отделна променлива - не става само с две звездички :))

(Функцията създава нова структура като ползва същия механизъм, с който е създадена входящата структура - тоя механизъм е някъде по модулите :).
Естествено, грижа се за освобождаване на заетата от входящата структура памет - поне така си мисля :))

От обясненията ти разбирам, че не е много тривиално. То и другия начин (с тип на функцията) става, но не е много удобен в някои случеи.


Вто Мар 15, 2011 10:06 pm
Профил ICQ WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Първо 20 пъти ти казах да си използваш типове а една структура като е дефинирана като тип не е необходимо да пишеш struct. Тоест кода ти


Код:
struct tBlaBla* change_BlaBla( struct tBlaBla* aBlaBla){
...
return xBlaBla; // не е aBlaBla :), a e xBlaBla
}


трябва да бъде

Код:
tBlaBla* change_BlaBla( tBlaBla* aBlaBla){
...
return xBlaBla; // не е aBlaBla :), a e xBlaBla
}


ама май не схвана какво ти казва колегата за върнатата структура. Запомни че всички променливи които са дефинирани в тялото на функцията,освен ако не са дефинирани като static се поместват в стека. Тоест при влизане в функцията първоначално в стека се заделя място за тях. При излизането от функцията това място в стека се освобождава.
И ако в твоята функция дефинираш структурата указател към която ще върнеш ще се получи че си върнал указател към структура която е в освободения вече стек. Ако междувременно извикаш друга функция,или при някои процесори дойде прекъсване то функцията ще си задели място в стека. Тоест ще разположи собствените си променливи върху адреса на твоята злополучна структура. И така ще се получи че НЕЗНАЙНО как структурата ти се е променила и ще ревнеш ААААА КОМПИЛАТОРА Е БЪГАВ ;)


Вто Мар 15, 2011 10:24 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Тоест може да върнеш структура само така

Код:
tBlaBla   xBlaBla;

tBlaBla* change_BlaBla( tBlaBla* aBlaBla){
...
return &xBlaBla; // не е aBlaBla :), a e xBlaBla
}


или така
Код:
tBlaBla* change_BlaBla( tBlaBla* aBlaBla)
{
static tBlaBla   xBlaBla;
...
return &xBlaBla; // не е aBlaBla :), a e xBlaBla
}


или така
Код:
tBlaBla* change_BlaBla( tBlaBla* aBlaBla)
{
tBlaBla *  xBlaBla = (tBlaBla *)malloc(sizeof  tBlaBla);
...
return xBlaBla; // не е aBlaBla :), a e xBlaBla
}


като в последния случай динамично заделяш памет,която като си свършиш работа със структурата трябва да освободиш с delete. Но не е много добра практика при работа с дребни процесори да се използва динамична памет.


Вто Мар 15, 2011 10:31 pm
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Съб Сеп 25, 2004 10:32 pm
Мнения: 710
Мнение 
Благодаря ти!
Структурата се създава с malloc (става дума за смяна на активната папка във FAT). Мисля, че коректно освобождавам "старата" структура (поне ползвам метода, който трябва да я освободи :)).
Все пак не разбрах - значи ли, че няма други начини, освен изброените 3?
Не мога да сменя адреса на входящия параметър aBlaBla и функцията да е void?

ПП
Относно двадесетте пъти - навярно поне толкова пъти се опитах да преработя частта от проекта, която ползвам на готово (за FAT) така, че да се ползват typedef.
Като се поизуча, може и да стане. За сега пречките са непреодолими :(.
Успокоява ме единствено мнението на
tolstolob написа:
...Начина, по който го е написал шваба е добър пример за мърлящина и ....
(малко по-горе в темата)


Сря Мар 16, 2011 12:27 am
Профил ICQ WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Код:
void change_BlaBla( tBlaBla** aBlaBla)
{
   *aBlaBla = (tBlaBla *)malloc(sizeof  tBlaBla);
}


или ако така по ти харесва

Код:
void change_BlaBla( tBlaBla* aBlaBla[])
{
   aBlaBla[0] = (tBlaBla *)malloc(sizeof  tBlaBla);
}


Сря Мар 16, 2011 2:46 am
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Съб Сеп 25, 2004 10:32 pm
Мнения: 710
Мнение 
Да, благодаря много!


Сря Мар 16, 2011 11:59 am
Профил ICQ WWW
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 10 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 3 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни