Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 18 kwi 2024, o 22:35


Strefa czasowa: UTC + 1





Utwórz nowy wątek Ten wątek jest zablokowany. Nie możesz w nim pisać ani edytować postów.  [ Posty: 64 ]  Przejdź na stronę Poprzednia strona  1, 2, 3  Następna strona
Autor Wiadomość
PostNapisane: 2 paź 2017, o 13:49 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

kisiel napisał(a):
A to że linker robi niejawną definicje, to już jest inna para kaloszy. Myślę że tym programem obaliłem ostatni mit na temat tego że zmienne są globalne tylko w momencie dopisania extern - poniakąd to jest prawda, ale to extern jest niejawnie dopisywane przez kompilator.


ale czy to nie oznacza, że podobnie jak z tym void należy wpisać to extern, bo w końcu mamy pisać z głową, a nie liczyć, że kompilator zawsze tak samo podejdzie?
Zresztą gdzie by nie spojrzeć piszą o tym, żeby pod żadnym pozorem nie umieszczać definicji w plikach nagłówkowych.
Choćby w książce Tomasza Francuza "AVR. Praktyczne projekty"

Obaliłeś mit albo nie obaliłeś, bo w końcu ten extern jest dopisany, więc jest potrzebny.

Zadajmy sobie pytanie czy zawsze będzie dopisany, czy to może będzie zależało od kompilatora czy tez opcji kompilacji?
Sam na to nie odpowiem, bo nie wiem, ale domyślam się.
Inaczej pisząc, dlaczego już w C++ extern jest konieczny?
Dla mnie dlatego, że prawdopodobnie twórca C++ wiedział, że to "extern czy nie extern" jest źródłem ciągłych błędów?
Tak sobie to tłumaczę...
Zresztą taka uwaga co do kodów, które zamieściłeś, tu nie dopiszesz tam, nie dopiszesz, kompilator coś doda lub nie doda, a jak wyjdzie to ok.
Mam ogromne wrażenie, że to nie jest dobra droga do programowania...



Góra
 Zobacz profil  
 
PostNapisane: 2 paź 2017, o 13:56 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

Zealota napisał(a):
Zadajmy sobie pytanie czy zawsze będzie dopisany, czy to może będzie zależało od kompilatora czy tez opcji kompilacji?


Nie nie - spokojnie - zasada jest prosta: "W przypadku zmiennych MUSI być specyfikator extern w plikach *.h ! bo to nie definicja i nie powoduje alokacji pamięci. I będzie to DZIAŁAĆ TAK SAMO w każdym kompilatorze C nie ważne gdzie

W przypadku funkcji - tzn nagłówków funkcji w pliku *.h można ale już nie trzeba pisać extern przed nagłówkiem. Dlaczego? Tu sprawa jest prosta, bo nagłówek kończy się średnikiem i nie ma nawiasów klamrowych a więc DOMYŚLNIE wiadomo, że to jest TYLKO nagłówek czyli DEKLARACJA a nie DEFINICJA funkcji

Qurczę - dlatego tyle czasu poświęciłem w Bluebooku żeby czytelnik zrozumiał te różnice - bo jak się to zrozumie to później MNÓSTWO rzeczy w C robi się jasnych. A jak się nie zrozumie - to się powiela takie błędy jakie robi kisiel albo roske.

------------------------ [ Dodano po: 2 minutach ]

Zealota napisał(a):
Inaczej pisząc, dlaczego już w C++ extern jest konieczny?
Dla mnie dlatego, że prawdopodobnie twórca C++ wiedział, że to "extern czy nie extern" jest źródłem ciągłych błędów?

I bardzo dobry wniosek - tyle że chodziło właśnie o takich programistów, którzy nie zrozumieli różnic w C pomiędzy deklaracją i definicją i ŁUPALI takie byki jakie widzimy "pięknie" w przykładowych kodach kolegi kisiel - i przysięgam, że nie chodzi tu o przytyk do kolegi kisiel albo jakieś mu dokuczanie - tylko o zwrócenie uwagi na BABOLE jakie się robi w C ... a później nie wie się często "co z czego wynika"

------------------------ [ Dodano po: 4 minutach ]

Zealota napisał(a):
Zresztą taka uwaga co do kodów, które zamieściłeś, tu nie dopiszesz tam, nie dopiszesz, kompilator coś doda lub nie doda, a jak wyjdzie to ok.

DOKŁADNIE - i tak można programować jakoś wiele lat, szczególnie gdy się pisze niewielkie projekty zawierające jeden albo ze 2-3 pliki ... przy większych mogę się założyć, że przy takim podejściu kolega kisiel niejednokrotnie spotkał się z babolami i pewnie próbował po omacku je naprawiać robiąc to na zasadzie "coś zmienię" i jak kompilator "łyknie" to znaczy że jest ok

------------------------ [ Dodano po: 9 minutach ]

TA PROSTA ZASADA dla zmiennych jest MEGA UNIWERSALNA i prosta jak drut w C

plik module.c

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.




plik module.h

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



i dlatego w C można spokojnie ten plik zapisać również tak:


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


jak widać w tym wypadku zniknął specyfikator extern przed nagłówkiem funkcji, ale próba wywalenia extern dla zmiennej skończyłaby się KICHĄ

No nie wiem czy można prościej to wyjaśnić

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 2 paź 2017, o 17:57 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 maja 2017
Posty: 143
Pomógł: 0

To już musi kolega roskę i kisiel sobie odpowiedzieć na to co dalej , bo przebywanie na tym forum to nie obrażanie , i przemądrzanie ale analiza i dążenie do coraz lepszych rezultatów w programowaniu no i pokory czego i wam życzę jak i wszystkim ;)

Ja oczywiście będę zadawał kolejne pytania, i czytam dalej ;)



Góra
 Zobacz profil  
 
PostNapisane: 2 paź 2017, o 19:21 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

i o to chodzi ....

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 08:58 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 sty 2016
Posty: 1148
Lokalizacja: Kraków
Pomógł: 93

Kolego roske, odwołujesz się do narzędzia objdump, ale tylko do wybranych jego opcji.
Nie opisałeś, co znaczy *UND* oraz *COM*. Znaczenie symbolu *UND*, Cytat:
Cytuj:
*UND* if the section is referenced in the file being dumped, but not defined there
Czyli co, obiekt, który nie został zdefiniowany w tym pliku? Czy źle zrozumiałem?
Natomiast znaczenie symbolu *COM*:
Cytuj:
SHN_COMMON Symbols defined relative to this section are common symbols, such as FORTRAN COMMON or unallocated C external variables.
Czyli? Zewnętrzna zmienna bez alokacji pamięci?

Źródła:
*UND*: https://sourceware.org/binutils/docs/bi ... jdump.html
*COM*: https://stackoverflow.com/questions/183 ... mbol-table
Wiem, że drugie źródło nie jest do końca pewne, ale nie mam możliwości dłużej się tym zająć.



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 12:19 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

Marhef napisał(a):
Czyli co, obiekt, który nie został zdefiniowany w tym pliku? Czy źle zrozumiałem?
Natomiast znaczenie symbolu *COM*:
Cytuj:
SHN_COMMON Symbols defined relative to this section are common symbols, such as FORTRAN COMMON or unallocated C external variables.
Czyli? Zewnętrzna zmienna bez alokacji pamięci?


DOBRZE zrozumiałeś ;)

No to teraz dla kolegi roske - nieco ŁOPATOLOGICZNIE ale jeśli ktoś chce zrozumieć naprawdę jakiego okrutnego BABOLA sobie roske wymyślił i na tej bazie wysnuł teorię na temat zmiennych globalnych języka C ... zresztą podobnie jak kolega kisiel .... Obydwaj nie rozumieją jak mi się wydaje z jednej strony co to znaczy zakres widoczności / przykrywanie nazw ... i zamiast sprawdzić swoje teorie porządnie to łapią się za jakiś wymyślony i kompletnie ŹLE napisany KOD i na tej podstawie "bo coś im zadziałało" wyjasniają teorie świata podkładając pod to angielskie okreslenia - których nie potrafią przełożyć na język polski ale to nic - nie rozumiem co to znaczy ale pewnie to wyjaśnia tajemnicze zjawisko.

Czekałem kolego roske - kiedy dojdziesz do opisu swojego przypadku - i w zasadzie po twoich zadętych postach gdzie piszesz np:
roske napisał(a):
Co Cię tak dotknęło? Fakt, że wiedza, którą pozyskałeś jest fałszywa, czy to że ktoś Ci to uświadomił?

to aż się dyskutować z takim osobnikiem nie chce - ale ...

ale w sumie i dobrze, że temat powstał - więc postaram się wyjaśnić jak ja to widzę a inni niech sami wyciągną wnioski ;)

Proszę bardzo - zgodnie z oczekiwaniami kolegi roske robieramy jego przykład na czynniki proste, że tak powiem ;) roske - przygotuj się.


Kolega tak mocno chciał żeby sobie każdy skompilował i zobaczył a później pisał że nikt nie skompilował - mając wszystkich za .... (szkoda gadać)

Obrazek

co widzimy na tym, jakże cudownym obrazku - otóż PIERWSZY przykładowy (skopany wg mnie) kod kolegi roske. Dlaczego skopany ? Proszę spojrzeć na tę czerwoną dwustronną przerywaną strzałkę. Tu kolega roske odstawia MEGA BONANZĘ ;) ... otóż w ramach jednego projektu DEFINIUJE dwie zmienne o takiej samej nazwie. (Podobnie jak kolega kisiel - widać, że nie rozumie co to jest DEFINICJA zmiennej) ... no i BACH! ... kompilator mu nie krzyczy, czyli "łyknął" jak to mawiał klasyk kisiel. WSZYSTKO NIBY DZIAŁA ... prawda - co więcej roske zaczyna karkołomne próby wyjaśnień dlaczego to działa pokazując objectdumpa z plików main.o oraz foo.o ... no to zajrzyjmy po naszemu:

ObrazekObrazek

co widzimy w foo.o - no widzimy, że kompilator WYRAŹNIE zarezerwował sobie adres w pamięci RAM na dwa bajty, w której będzie przechowywana zmienna o nazwie dwa. I to jest OBIEKT ale widać, że ładnie zaadresowany w obszarze: .data.dwa

co natomiast widzimy w main.o ? No tu widzimy również obiekt ale niestety ma on co ciekawe rozmiar = 1 ;) natomiast u roske ma rozmiar 4 - kto zgadnie dlaczego ? Poza tym obiekt opisany jako COM, jest jak słusznie wyżej zauważył wyżej kolega Marhef, unallocated C external variables.

hmmm no jak to? myśli sobie kolega roske ? zresztą tak naprawdę to nie wiem co on myśli i co miały pokazać jego przykłady ... ale spróbujmy rozważyć dlaczego na wyświetlaczu LED

koledze roske niestety nie chciało się...
roske napisał(a):
(oczywiście, aby się nie motać z żelastwem, kompilacje i uruchamianie robimy na PC)


a szkoda, bo jakbyś sobie zadał minimu trudu i zauważył chociażby tę różnicę w rozmiarach: 4-bajty dla zmiennej dwa na PC, 2-bajty dla zmiennej dwa na AVR8 - no i ten tajemniczy rozmiar = 1 dla obiektu COM .... to już mogłoby cię to na coś naprowadzić. Tymczasem z jakąś przedziwną radością piszesz takie bzdurki:

roske napisał(a):
Przykład nie powinien się nawet dać skompilować, nieprawdaż?


roske ależ powinien się skompilować - tylko ty nie wiesz dlaczego tak się stało w tym przypadku a zaraz tobie pokażę przypadki kiedy się nie skompiluje i będziesz MOCNOOOO zdziwiony ...

otóż program się kompiluje TYLKO dlatego, że uznaje, że ktoś zdefiniował dwie zmienne przy czym (Uwaga! roske) nie zainicjalizował zmiennej "dwa" w pliku main.c ! W związku z tym nazwa ta otrzymała specyfikator COM - uznana została za zewnętrzną zmienną globalną ale tylko dzięki temu że nastąpiło przysłonięcie nazw z dwóch różnych klas.

no to teraz DRUGI WARIANT - roske popatrz - komentujemy linię w main.c

// dwa = 200;

Obrazek

OOO maaaj gaaad - i co my widzimy ;) ? Ale ja nie będę zadawał zagadek jak roske, ponieważ wyciągnąłem żelaztwo - bo lubię to proszę na LCD tym razem CUD się stał - dżizas! zamiast liczby 200 wyświetliła się nam liczba 2

pewnie roske teraz się cieszy bo to wg niego dowód na jego pomysł globalności ... Oczywiście jak zajrzymy do object dumpa to zobaczymy DOKŁADNIE to samo co wyżej !!! A więcnadal zadziała przysłanianie nazw ale TYLKO dlatego, że zmienna "dwa" zdefiniowana w main.c nie została zainicjalizowana!

W takim razie spróbujmy ją zainicjalizować jakąś wartością np 17 ;) a kto nam zabroni? - proszę bardzo:

Obrazek

uuuuuuu .... buuuu - ooo jej - no i kompilator w końcu zwymiotował ... a ja się mu wcale nie dziwię. Też bym to zrobił, gdyby ktoś próbował mnie faszerować takim kodem ...

czyli co widzimy w czarnej ramce ?

Cytuj:
./main.o:(.data.dwa+0x0): multiple definition of `dwa'


roske - jak to? dlaczego ? No i w łeb wzięła teoria o tego typu globalności ....

No to teraz popatrz roske na ostatni obrazek, ponieważ jak się domyślam zaraz znowu wymyślisz jakieś teksty o fałszywości itp, tymczasem przekonaj się sam ;)

Obrazek

dodałem nad funkcją main() nową funkcję o nazwie fun1, i wywołałem ją przed nadaniem nowej wartości = 300 zmiennej dwa. Tyle że podczas kompilacji kompilator najpierw MUSI ustalić miejsce w RAM dla zmiennej dwa i gdzie została przydzielona pamięć ? oczywiście w foo.c ponieważ w objecdupie foo.o widzimy tę rezerwację. Natomiast znowu - kompiluje się to ponieważ zmienna "dwa" z main.c jest tylko wydmuszką ! ;)

Teraz jeszcze raz sobie spróbuj zainicjalizować zmienną "dwa" w main.c i zobaczysz znowu figę z makiem od kompilatora:

Obrazek

widzisz Pan? ... i to co pokazałem strzałką i podkreślone - kompilator nie na darmo krzyczy że wcześniej taka zmienna została zdefiniowana w foo.c ! a że próbowałeś zainicjalizować JEDNĄ i DRUGĄ na etapie gdy kompilator będzie musiał umieścić to w BSS to dostaje ŚWIRA - bo nie wie - którą wartością, nie może tu już dojść do przysłonięcia nazw - ponieważ jawnie próbujesz inicjalizować dwa obiekty o TAKIEJ SAMEJ NAZWIE

Więc BZDURĄ jest twoja i kiśla teoria o pseudo waszej wymyślonej globalności ....

--------------------------------------------------------------------------------------------------------------

Tymczasem gdybyście DOKŁADNIEJ poczytali klasykę na temat ANSI C jak w wydaniu :

The C Programming Language - Kernighan and Ritchie

albo chociaż Praty to byście w końcu zrozumieli co to jest DEFINICJA zmiennej i jej DEKLARACJA i czym się różnią ! Wtedy byście nie pietruszkowali tego co do tej pory tylko napisalibyście ten kod jak się należy czyli - DEFINICJA zmiennej np w foo.c, do tego jej DEKLARACJA w foo.h (dokładnie tak samo jak ze zmienną "jeden" w twoim przykładzie i WSZYSTKO by pięknie działało !) .... zamiast się upierać jak piszesz z uporem maniaka przy wydumanych teoriach albo jak kisiel pisać , że ja rzekomo ogłaszam jakieś swoje zasady ! Bzdura - ja się tylko uczę i to co doczytam u klasyków albo stwórców C to wtedy się tym dzielę. Oczywiście mogę się mylić, mogę popełniać błędy - być może nawet w tych wyjaśnieniach coś mało precyzyjnie opisałem ... ale myślę, że teraz są jasne i przejrzyste.

Już nie wspomnę , że pisałem tobie roske abyś dla przykładu założył kolejny plik np foo2.c w którym powołasz kolejny raz definicję zmiennej o nazwie "dwa" - to sam wiesz, że już taka głupota się nie uda od razu z marszu - bo kompilator wywali błąd ... ale ty rozbrajająco napisałeś - no i co z tego, że wywali ? ;)

Na koniec - zamiast zadętych tekstów o fałszywości, o biciu piany i tym podobnych - ochłoń, przeczytaj na spokojnie - a jak będziesz miał jeszcze jakieś uwagi albo nie będziesz się zgadzał z tym co ja pokazałem to napisz - chętnie podyskutuję dalej - ale pod warunkiem, że zaczniesz dyskutować kulturalnie i już na luzie ok ?

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 12:45 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

UWAGA. Posta tego pisałem zanim Mirek odpowiedział, ale i tak wrzucam to i tak jak myślałem pewnie trza coś będzie sprostować.


roske napisał(a):
Chciałbym z uporem maniaka wrócić do swoich przykładów programów, tych z postu topic19291.html#p196281, chodzi o wariant pierwszy. Przykład nie powinien się nawet dać skompilować

Ale niby dlaczego. Chyba coś pominąłem w całym wątku...

roske napisał(a):
To znaczy zgodnie z moim oczekiwaniem, bo zgodnie z wersją obowiązującą na forum globalna jest tylko zmienna "jeden


Obie są globalne, bo jedną zdefiniowano w main.c a drugą w foo.c, obie w sekcjach zmiennych globalnych oraz zmienna dwa poprzez extern jest widoczna w main.c i jest globalna.

Wg mnie globalna to nie oznacza od razu widoczna.
Zresztą co może oznaczać extern, no chyba external, czyli zewnętrzna.
Przyrównałbym to do pojęcia sieci komputerowych lokalnych. Jeśli nie ustawimy routingu (widoczności) to taka sieć nie ma dostępu "do morza".
Taki routing odpowiada słówku extern.

Wynik zadziałania taki:
Składnia: [ Pobierz ] [ Ukryj ]
język bash
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Funkcja fun(), przy wywołaniu w main, nie widzi zmiennej dwa (od foo.c ), bo jest "poza zakresem widoczności", a nie dlatego, że ktoś twierdzi, że jest lokalna

Do powyższego jeszcze rozumiem (lub tak mi się wydaje :).

Jeśli wywalimy z fun() zapis "int dwa = 2;" to mamy błąd: "error: 'dwa' undeclared (first use in this function)"
no i chyba to zrozumiałe, bo fun() nie wie co to dwa, bo nie widzi tego z fun().
Mam za to pytanie: skoro fun()krzyczy o dwa znajdujące się w foo.c to czemu w main.c korzysta z dwa.
Spróbuję sam sobie na to odpowiedź, rozchodzi się tu a kompilator i linker. Ten pierwszy "skupia się" tylko nad modułami, a linker również nad zależnościami między
modułami.

Jeszcze ważne, jeśli gdzieś się pomyliłem to poprawcie...

PS
Zrobiłem jeszcze inny eksperyment,
Z funkcji main() usunąłem przypisanie "dwa = 200" i otrzymałem:
Składnia: [ Pobierz ] [ Ukryj ]
język bash
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Zgłupiałem i nie wiem co o tym sądzić :)

Potem w main() od razu zainicjowałem zmienną "int dwa=500;"
i już otrzymuję błąd "multiple definition", ale to już kwestia linkera

To ostatnie też Mirek opisał w swoim, równoległym poście :) choć czytam to i jeszcze nadal nie rozumiem :)

------------------------ [ Dodano po: 5 minutach ]

Zealota napisał(a):
Obie są globalne, bo jedną zdefiniowano w main.c a drugą w foo.c


A chyba jednak babol. Ta druga przecież wcale nie jest zdefiniowana tylko zadeklarowana :)



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 12:51 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

Zealota napisał(a):
Z funkcji main() usunąłem przypisanie "dwa = 200" i otrzymałem:

Zealota napisał(a):
Zgłupiałem i nie wiem co o tym sądzić

To przeczytaj na spokojnie przy kawie moje precyzyjne wyjaśnienie - gwarantuję, że wszystko stanie się absolutnie jasne ;) dlaczego tak się dzieje i skąd się bierze

a swoją drogą to bardzo dobre wnioski wyciągasz z tego co sam obserwujesz ;) a tam gdzie mogę to ja też coś podpowiem (patrz mój post wyżej) i spokojnie dojdziemy ło co tutaj panie dzieju chodzi ;) ... mam nadzieję, że kolega roske też zrozumie

------------------------ [ Dodano po: 1 minucie ]

Zealota napisał(a):
Ta druga przecież wcale nie jest zdefiniowana tylko zadeklarowana

Toż OBYDWIE zmienne o nazwie "dwa" są ZDEFINIOWANE ;) jedna w main.c zaś druga w foo.c - proszę przeczytaj wyżej moje wyjaśnienie

------------------------ [ Dodano po: 1 minucie ]

Zealota napisał(a):
choć czytam to i jeszcze nadal nie rozumiem

ale to powiedz od którego momentu ?

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 12:59 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

roske napisał(a):
Konsolidator się wywala, ale kompilator nie, z powodzeniem tworzy sobie "main.o" (dalej nie będę się szamotał z żelastwem bo target jest CAŁKOWICIE bez znaczenia). Zaglądamy do niego objdumpem i...tada...

nie tada... tylko teraz zauważ, że korzystamy z różnych kompilatorów ... i co to wg ciebie oznacza? jak chodzi o ANSI C ?

Ty się wciąż upierasz - że coś tam się wywala np konsolidator ale kompilator nie ... no toż zrozum - co to ma wspólnego z prawidłowym podejściem?

Po trzecie - ZAŁÓŻ ŻE PLIK --- FOO1.c i tam zdefiniuj po raz kolejny zmienną dwa - i skompiluj

------------------------ [ Dodano po: 2 minutach ]

a nadmienię, że mówimy o toolchanie a nie o jakimś JEDNYM programie - więc jeśli jedno z ogniw pada to po co pisać, że jest OK

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 13:07 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

roske napisał(a):
...zmienna dwa odzyskuje swoją "globalnowato-alokowalność". Są dwie zmienne globalne, konsolidator nie może tego rozwiązać. Co się stało? Zastosowanie znalazło "tentative definition":

W AVR GCC jak widać to nie zadziała co ci pokazałem i udowodniłem a ty dalej z uporem maniaka dowodzisz swojego - zamiast podchodzić do zmiennych globalnych jak się należy i nie byłoby żadnego problemu ;) jak mówię skompiluj trzeci plik z trzecią definicją tej samej zmiennej - ja nie mam kompilatora C na PC więc nie mam jak sprawdzić - może u ciebie też zadziała ;)

Tyle że NAWET jeśli zadziała to fakt, że kodzie projektu w 40 plikach będziesz miał definicję zmiennej "dwa" - zamiast rozprzestrzeniać jej widoczność za pomocą extern - jest po prostu (delikatnie mówiąc) tragicznym pomysłem na podejście do programowania

------------------------ [ Dodano po: kilkunastu sekundach ]

roske napisał(a):
mirekk36 napisał(a):
korzystamy z różnych kompilatorów

Ja używam GCC. A Ty nie AVR-GCC? ...Czyli GCC.


No i co? dla ciebie nie ma różnic ? pomimo że pokazałem ci objecdumpy ? z AVR ?

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 14:18 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

a teraz roske - co to jest "tentative definition" - to nie jest trudne - także nie jest trudne do przetłumaczenia na polski ;)

Ja bym to nazwał "niepewną definicją" ... albo może lepiej "orientacyjną definicją" ... o co chodzi ?

Otóż ta reguła "tentative definition" wprowadzona do C pozwala na utworzenie wielu definicji tej samej zmiennej i najwyżej jedna z nich posiada jawny inicjalizator. A zatem taki kod:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


też się skompiluje dzięki tej regule - co może wydawać się dziwne, ale kompilator C tak "z tyłu zza węgła" łączy wszystkie wstępne definicje w jedną definicję. I masz rację, że zachodzi tu jak pisałeś "tentative definition" ale na ZEUSA no BZDURĄ jest tworzenie definicji o tej samej nazwie i to w różnych plikach ! Co to ma w ogóle wspólnego z pojęciem zmiennych globalnych ?

dla twojej wiadomości:

1. extern int dwa;
2. int dwa;


czym to się różni ? otóż PIERWSZY zapis to DEKLARACJA z linkowaniem zewnętrznym (external linkage)
DRUGI zapis to jest panie DEFINICJA a ta dzięki regułom "tentative definition" jest również z linkowaniem zewnętrznym (external linkage) Dzięki czemu może w ogóle dojść do połączenia definicji zmiennej dwa w twoim przykładzie pod jednym adresem w RAM.

I teraz - jak się spojrzy na taki projekt gdzie będą trzy pliki:

main.c
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



foo1.c
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



foo2.c
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


i w każdym definicja zmiennej o nazwie "dwa" to też się skompiluje dzięki temu mechanizmowi .... ale czy TAK PISZE się programy ? No bój się Pan Boga! ... Ty chcesz używać świadomie "tentative definition" - w KAŻDYM projekcie pisząc tę samą DEFINICJĘ zmiennej ? sorry ale to już wręcz niedorzeczność - owszem to zadziała ale to MEGA BZDURA - tyle że pokazuję ci dlaczego to zadziała

zamiast więc pisać z uporem maniaka - jak sam to określałeś - WYSTARCZY korzystać z PRZEJRZYSTEGO określania zakresu widoczności zmiennych, które mają być GLOBALNE - dla innych plików ... toż wystarczy na ZEUSA tylko w jednym pliku *.h tak jak to zrobiłeś ze zmienną "jeden" użyć extern !

extern int dwa;

czym JASNO określasz zakres widoczności i linkowania tej zmiennej. Widząc to w kodzie - JESTEM nie tylko przekonany, że gdzieś w jednym z np 50-ciu plików projektu znajduje się JEDNA (Qurczę) DEFINICJA zmiennej - która może być również jawnie inicjalizowana ....


-------------------------------------------------------

i na sam KONIEC chłopie teraz o ile nie bawisz się w pisanie kodu w konsoli tylko w jakimś porządnym ;) graficznym środowisku jak ECLIPSE ;) zrób sobie taki mały niewinny super krótki teścik;

Gdy będziesz miał w tych trzech plikach w KAŻDYM definicję "dwa" to spróbuj trzymając wciśnięty LEWY CONTROL plus kliknięcie MYCHĄ - kliknąć na nazwie "dwa" ..... KICHA ! nic się nie stanie bo stoisz niby na definicji - ale tych fantomowych definicji masz aż trzy ?

Za to kliknij sobie w ten sposób na nazwę "jeden" w main.c ;) i zobacz jak ładnie poprowadzi cię środowisko do miejsca gdzie jest DEFINICJA tej zmiennej !

----------------------------------

jak sobie zrobisz te trzy pliki - to zauważ, że ZAWSZE w pliku w którym będziesz miał inicjalizację zmiennej "dwa" to w objectdumpie zobaczysz

Kod:
O .data.dwa


zaś w pozostałych plikach

Kod:
O *COM* 00000001 dwa


u mnie tu na końcu będzie jeden a u ciebie 4 - ale jak pisałem wcześniej to zagadka dlaczego ;) ?

------------------------ [ Dodano po: 5 minutach ]

gdzieś znalazłem takie wyjaśnienie:

Cytuj:
Tentative definitions were invented to standardize various pre-C89 approaches to forward declaring identifiers with internal linkage.


więc kończąc - ma to tyle wspólnego z twoim pojęciem globalności co ... no właśnie co z czym ?

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 14:26 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

mirekk36 napisał(a):
Zealota napisał(a):
Ta druga przecież wcale nie jest zdefiniowana tylko zadeklarowana

Toż OBYDWIE zmienne o nazwie "dwa" są ZDEFINIOWANE ;) jedna w main.c zaś druga w foo.c - proszę przeczytaj wyżej moje wyjaśnienie

------------------------ [ Dodano po: 1 minucie ]
ale to powiedz od którego momentu ?

No tak walnąlem kulą wpłot. Wracam do przemyśleń na temat definicji i deklaracji :)

Zealota napisał(a):
choć czytam to i jeszcze nadal nie rozumiem


Nadal to jest takie rozwleczone. Gdzieś dzwoni, ale nie wiadomo gdzie :)
Powrócę na razie do stwierdzenia:

"Obie są globalne, bo jedną zdefiniowano w main.c, a drugą w foo.c, obie w sekcjach zmiennych globalnych oraz zmienna dwa, poprzez extern, jest widoczna w main.c i jest globalna."
Jednak źle to chyba napisałem, chodziło oczywiście o zmienną jeden, bo to ona ma extern i jest globalna oraz widoczna dla tych co inkludują foo.h.
Zgadza się teraz?

Natomiast dwa jest zmienną globalną, bo umieszczono ją w sekcji zmiennych globalnych pliku foo.c, ale nie jest widoczna dla innych modułów, nawet jeśli includują foo.h, bo nie ma jej deklaracji poprzedzonej extern w pliku foo.h?

Czy może robi się z niej lokalna, bo zabrakło extern i deklaracji w nagłówku foo.h?

A może brak widoczności, pomimo umieszczenia w sekcji zmiennych globalnych, automatycznie robi ze zmiennej lokalną?

A może to po prostu nieporozumienie: umieszczenie w sekcji zmiennych globalnych, ale ograniczenie widoczności powoduje, że ktoś uważa, że jest lokalna?
Taki błąd komunikacyjny?

Co zatem ze zmienną static w jakiejś funkcji.
Piszą, że to jest "zmienna lokalna, ale umieszczona w sekcji zmiennych globalnych", która jest widoczna tylko dla tej konkretnej funkcji, gdzie nastąpiła definicja.
Czy takie umieszczenie nie robi z niej jednak globalnej, tak jak te nieszczęsne dwa :)

Może źle rozumiem "sekcja zmiennych globalnych" i nie chodzi tu o miejsce w plikach źródłowych ".c", tylko o miejsce w pamięci?
Dla mnie to miejsce to: "wszędzie" poza funkcjami w plikach źródłowych, a wg dobrych zasad zaraz za includami?

Zatem te wyniki, które wspólnie kompilowaliśmy...

Dlaczego mamy w wyniku 200? Bo dwa z funkcji main() zasłoniła dwa z foo.c?
Dlaczego zatem w kolejnym przypadku jest już 2, gdy nie przypiszemy 200 w funkcji main(), bo nagle "wskoczyło" dwa z foo.c :)

Poczytam jeszcze te wcześniejszy obszerny wywód, ale moje wątpliwości właśnie tu się kumulują, w tych powyższych zdaniach :)
Co zrobić jak talentu poskąpiło :)

mirekk36 napisał(a):
Po trzecie - ZAŁÓŻ ŻE PLIK --- FOO1.c i tam zdefiniuj po raz kolejny zmienną dwa - i skompiluj


Ja to zrobiłem, bo nie wytrzymałem :). I co bym nie robił, jak nie kombinował, zawsze jest error "multiple definition".
Nawet gdy foo2.c ma tylko jedną linijkę int dwa = 3; .
Zawsze linker się pluje, bo chyba właśnie tak działa, że nie mnoży nie potrzebnych bytów :)

No chyba, że zamienimy na int dwa; już jest bez błędów hmm....
Taka definicja jest usuwana przez kompilator? Bo nie rezerwuje pamięci i jest ogólnie niepotrzebna? Podobnie jak w przykładzie nr 1 Kolegi roske?
Czy to chodzi o te magiczne 1 vs 4 od Mirka? :)

Dobra tyle tego dumania...



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 14:38 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

Zealota napisał(a):
"Obie są globalne, bo jedną zdefiniowano w main.c, a drugą w foo.c, obie w sekcjach zmiennych globalnych oraz zmienna dwa, poprzez extern, jest widoczna w main.c i jest globalna."

no tak - obie zmienne o nazwie "dwa" w obu plikach są globalne względem tych plików ale dzięki "Tentative definitions" posiadają coś takiego jak "external linkage" dzięki czemu kompilator może te dwie zmienne o nazwie "dwa" widzieć pod jednym adresem RAM. Ale jak już zdążyłem napisać w kolejnym poście - gdyby w ten sposób chcieć korzystać z globalności zmiennych - to sam popatrz ;) zamiast dawać zmienną "dwa" tak jak "jeden" ze specyfikatorem extern do pliku "h" to co ? logicznym wydaje się napierniczanie w KAŻDYM pliku w którym chcesz użyć tej zmiennej "dwa" aby była widoczna w całym projekcie ???? Toż to byłaby bzdura ;) a pomyśl o bibliotekach ;) to już w ogóle nie dałoby rady zrobić - bo byś musiał kazać użytkownikowi swojej biblioteki definiować w KAŻDYM własnym pliku zmienną "dwa" zamiast przekazać ją jako "extern int dwa" przez plik nagłówkowy biblioteki ... no tu roske popłynął

mirekk36 napisał(a):
Natomiast dwa jest zmienną globalną, bo umieszczono ją w sekcji zmiennych globalnych pliku foo.c, ale nie jest widoczna dla innych modułów, nawet jeśli includują foo.h, bo nie ma jej deklaracji poprzedzonej extern w pliku foo.h?

Tak nie jest widoczna dokąd nie zadziała Tentative definitions - co WCALE NIE SPOWODUJE, że każda z nich stanie się widoczna dla innego pliku ale spowoduje, że kompilator zrobi porządek za plecami i obydwie zmienne przypisze do JEDNEGO adresu w RAM ... i będzie to dziwnie wyglądało nieprawdaż ? ;)

Zealota napisał(a):
Czy może robi się z niej lokalna, bo zabrakło extern i deklaracji w nagłówku foo.h?

Nie, jest tak jak wyżej doprecyzowuję

Zealota napisał(a):
A może brak widoczności, pomimo umieszczenia w sekcji zmiennych globalnych, automatycznie robi ze zmiennej lokalną?

też nie - patrz wyżej "Tentative definitions"

Zealota napisał(a):
Co zatem ze zmienną static w jakiejś funkcji.
Piszą, że to jest "zmienna lokalna, ale umieszczona w sekcji zmiennych globalnych", która jest widoczna tylko dla tej konkretnej funkcji, gdzie nastąpiła definicja.
Czy takie umieszczenie nie robi z niej jednak globalnej, tak jak te nieszczęsne dwa


nie nie nie ;) nie ... spokojnie na pewno wiedziałeś co robi static albo co zrobiłby dla zmiennej dwa ale pewnie zapomniałeś. Specyfikator static daje tylko powiązanie wewnętrzne czyli zmienna będzie mogła być widoczna TYLKO I WYŁĄCZNIE w ramach tego samego pliku i będziesz miał błąd nawet jak spróbujesz ją wyeksportować przez plik h za pomocą extern ;) - to całkiem oddzielna sytuacja. Wyłączamy widoczność dla innych plików jeśli chodzi o zmienne globalne w pliku jeśli dajemy im static

------------------------ [ Dodano po: 5 minutach ]

Zealota napisał(a):
Może źle rozumiem "sekcja zmiennych globalnych" i nie chodzi tu o miejsce w plikach źródłowych ".c", tylko o miejsce w pamięci?
Dla mnie to miejsce to: "wszędzie" poza funkcjami w plikach źródłowych, a wg dobrych zasad zaraz za includami?

DOBRZE rozumiesz - chodzi o miejsce i widoczność w pliku źródłowym - zaś możliwość powiązań później zależy albo od EXTERN albo od tego co robił roske czyli znowu - reguł "Tentative definitions"

------------------------ [ Dodano po: 6 minutach ]

Cytuj:
Dlaczego mamy w wyniku 200? Bo dwa z funkcji main() zasłoniła dwa z foo.c?

Bo jednak kompilator połączył obie zmienne "dwa" pod jednym adresem. Udało się to dzięki ? ... "Tentative definitions" ;)

------------------------ [ Dodano po: 10 minutach ]

Zealota napisał(a):
Dlaczego zatem w kolejnym przypadku jest już 2, gdy nie przypiszemy 200 w funkcji main(), bo nagle "wskoczyło" dwa z foo.c


No bo teraz zobacz - a to jest CIEKAWE i dlatego pokazałem taki przypadek

Najpierw wykonuje się funkcja fun1() prawda ? Zmienna "dwa" dzięki (mantra) Tentative definitions - ma ten sam adres a jej inicjalizacja nastąpiła w foo.c i na wartość = 2 zgadza się ? ;) Dlatego zanim nie zmienimy tej wartości to ukazała nam się wartość = 2 ! Następnie w main() przypisując wartość 200 zmieniamy z 2 na 200 ;) bo znowu mamy do czynienia z tym samym adresem w RAM

ale tym przypadkiem chciałem pokazać również koledze roske - jakie głupoty mogą wychodzić podczas analizy kodu - i nie dziwię się, że ty Zealota się dziwisz skąd się wzięło 2 - ale teraz już chyba jasne ? ;)

------------------------ [ Dodano po: 12 minutach ]

Zealota napisał(a):
Ja to zrobiłem, bo nie wytrzymałem . I co bym nie robił, jak nie kombinował, zawsze jest error "multiple definition".
Nawet gdy foo2.c ma tylko jedną linijkę int dwa = 3; .
Zawsze linker się pluje, bo chyba właśnie tak działa, że nie mnoży nie potrzebnych bytów


Jeśli w trzech plikach - ZROBISZ TYLKO jedną inicjalizację to oczywiście zadziała ;) sprawdź to też sobie ;) - warto sprawdzać to na naszym złomie prockowym - bo wtedy człowiek się najwięcej uczy wg mnie ;)

ale też dzięki temu zrozumiesz jak i dlaczego działa Tentative definitions, które kolega roske pomylił sobie z globalnością w całym projekcie - QUNIEC na razie ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 19:39 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 26 maja 2017
Posty: 143
Pomógł: 0

Mirku jeszcze jedno w tym temacie bo dziś na to się natknąłem a o to nie spytałem i nie daje mi św.spokoju , nasunęło mi się kolejne pytanie , podejrzewam jak postąpić ale nie jestem pewien dlatego popraw mnie .


definiuje załużmy zmienną globalną w main.c w projekcie składającym się z plików main.c i pomoc.c

Kod:
//***main.c

int globalna=4;  // zmienna globalna, którą chce uwidocznić w pliku pomoc.c

int main(void){
}


Co zrobić jeśli main.c nie ma swojego pliku nagłówkowego i nie można przerzucić do niego deklaracji zmiennej globalnej extern,
bo nie ma pliku main.h przerzucić tą deklaracjie extern int globalna do pomoc.h , by uwidocznić ją, dla pliku pomoc.c , w którym chce się zapewnić dostęp do niej ?


ja bym przerzucił deklaracjie do pliku nagłówkowego pomoc.h , ale nie wiem czy dobrze myśle?

main.c
Kod:
//***main.c

int globalna=4;

int main(void){
orange();
}


pomoc.c

Kod:
//**pomoc.c

void orange (void){
globalna=6
}

}



Kod:
//**pomoc.h
#ifndef GH_H_
#define GH_H_


extern int globalna;

void orange(void);

#endif /* GH_H_ */
}



Góra
 Zobacz profil  
 
PostNapisane: 3 paź 2017, o 20:05 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

Wydaje mi się, że już kiedyś o tym i to tobie pisałem - ale może mi się wydaje ;) więc jeszcze raz:

procek87 napisał(a):
Co zrobić jeśli main.c nie ma swojego pliku nagłówkowego


A dlaczego piszesz, że on nie ma swojego pliku? A kto tak powiedział? ;) toż to od ciebie zależy, toż możesz sobie stworzyć plik main.h - kto ci zabroni - i tak czasem ludzie robią - ale mi się to nie do końca podoba osobiście , ja wolę nieco inne podejście - ale to tylko moja propozycja a nie że ja mówię że tak trzeba. Ja po prostu tak robię w swoich programach.

PO PIERWSZE - ZAWSZE warto umieszczać zmienne w plikach z którymi one się jakoś wiążą logicznie, w których są najczęściej używane a rzadziej będą używane w innych plikach projektu.

Podajesz tu przykład troszkę oczywiście oderwany od rzeczywistości - ale fajnie że prosty przykład oczywiście ...

otóż zakładając, że zmienna pomoc miałaby być wykorzystywana zarówno w main.c ale też w innych przypadkowych plikach projektu - to ja z marszu zakładam sobie w ścieżce głównej projektu od razu dwa pliki:

common.c
common.h

i już sam czujesz, że właśnie umieściłbym jej definicję w pliku common.c zaś deklarację w common.h a następnie tam gdzie będę jej potrzebował czy to w main.c czy w innych plikach - rozumiesz? Zawsze w plikach "common" wtedy umieszczam tego typu wspólne i nie mające logicznego powiązania zmienne z konkretnym modułem. Podobnie z jakimiś wspólnymi funkcjami czy definicjami preprocesora

ALE ... ty tu w tym przykładzie napisałeś że potrzebujesz zrobić pliki

main.c

pomoc.c
pomoc.h


no to jak widzę nazwę zmiennej "pomoc" to sam powiedz - nie wiąże się ona logicznie z tymi plikami pomoc.c -.h ??? A jeśli tak to niestety wymyśliłeś NAJMNIEJ zdrowe podejście, żeby:

a) DEFINICJĘ tej zmiennej walnąć w main.c
b) DEKLARACJĘ tej zmiennej dać w pomoc.h

ja bym jak pisałem wyżej dał jej definicję w pomoc.c, jej deklarację w pomoc.h i zainkludowałbym w main.c plik pomoc.h

Mam nadzieję, że teraz jaśniej ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 09:29 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 paź 2014
Posty: 233
Lokalizacja: Rzeszów
Pomógł: 11

A jak postępować ze zmiennymi będącymi strukturami?
W wielu miejscach natchnąłem się: "ten iclude musi być pierwszy bo inaczej nie działa"

Zrobiłem mały test - definicję nowego TYPU zmienne strukturalnej wrzuciłem do common.h, definicję ZMIENNEJ strukturalnej do common.c, deklarację tejże zmiennej (ze słowem extern) do common.h.
Tam, gdzie includuję comon.h i z niej korzystam jest niby ok - program się kompiluje, nie wywala błędów, ale robiłem to trochę jak ruski saper - "na macajewa".

_________________
Mr. Nobody



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 09:39 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

APAP75 napisał(a):
Tam, gdzie includuję comon.h i z niej korzystam jest niby ok - program się kompiluje, nie wywala błędów, ale robiłem to trochę jak ruski saper - "na macajewa".


Nie, nie zrobiłeś jak ruski saper - zrobiłeś MEGA POPRAWNIE:


common.c
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



common.h
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


main.c
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 09:41 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

Szanowni Czytelnicy, jeszcze pociągnę temat deklaracji i definicji, bo chyba wreszcie wbiłem sobie to do głowy, może komuś jeszcze to pomoże.
Przygotowałem kilka cytatów z czeluści ksiąg tajemnych i internetów :)

Cytat z niniejszego wątku:
mirekk36 napisał(a):
1. extern int dwa;
2. int dwa;


czym to się różni ? otóż PIERWSZY zapis to DEKLARACJA z linkowaniem zewnętrznym (external linkage)
DRUGI zapis to jest panie DEFINICJA a ta dzięki regułom "tentative definition" jest również z linkowaniem zewnętrznym (external linkage) Dzięki czemu może w ogóle dojść do połączenia definicji zmiennej dwa w twoim przykładzie pod jednym adresem w RAM.


Na potwierdzenie jeszcze raz to samo źródło, czyli BB. Pozwolę sobie zacytować cześć dot. zmiennej:
"Przykłady Deklaracji:
extern int a1;
extern uint8_t tab[];
Przykłady Definicji:
int b1;
int c2 = 5;" Koniec cycatu :)

Szukamy zatem innego źródła: "Podstawy języka C++" Stanley B. Lippman"

"Definicja zmiennej służy do zarezerwowania dla tej zmiennej, wprowadzenia jej nazwy i określenia typu"
"Deklaracja służy do oznajmiania, że zmienna taka istnieje i została zdefiniowana w innym miejscu programu. Deklaracja składa się ze specyfikatora typu oraz nazwy zmiennej, poprzedzonych słowem kluczowym extern"

Najważniejszy wniosek dla mnie tutaj płynie taki, że jawne pisanie extern wskazuje bezbłędnie na deklarację, zatem używajmy go wszędzie gdzie trzeba, nie liczmy na kompilator. Poprawne użycie tego słowa zwiększa czytelność kodu!

A teraz pojęcia prosto z "interneta":
http://cpp0x.pl/forum/temat/?id=20322
No i mamy podsumowanie:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Zapis ten, wg mnie, sugeruje, że tylko jawna (przez użytkownika) inicjalizacja zmiennej zrobi z tego zapisu definicję
Jeśli nie sugeruje tego autor intencjonalnie, to sam zapis i brak wyjaśnienia mąci innym w głowach, bo faktycznie użytkownik nie musi jawnie inicjować zmiennej, żeby była definicją, zrobi to automatycznie kompilator - bo taki jest standard języka C.
Zatem każda definicja zmiennej rezerwuje pamięć i daje jej wartość. Użytkownik oczywiście tę wartość może zmienić, ale to banał :)

Zapis:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

to oczywisty błąd, zapis ten nie jest deklaracją.
Linijka ta oczywiście jest definicją, bo nie zawiera słowa kluczowego "extern". Niestety, jak wiemy z wątku, to bardzo potrzebne "extern" jest najczęściej doklejane przez kompilator jeśli go brakuje w plikach nagłówkowych, stąd mogą rodzić się nieporozumienia.

No i chyba wreszcie zaskoczyło i łatwiej mi już dzielić na pliki, błędów nie ma i jest git :)

Powrócę za to jeszcze do rodzaju zmiennych, czy lokalna czy globalna.
Uknułem sobie taką oto skrótową definicję: każda definicja zmiennej wewnątrz funkcji robi z niej zmienną lokalną.
Wszystkie inne definicje (poza funkcjami, również poza main() ) to są zmienne globalne, są bowiem umieszczone w sekcji zmiennych globalnych, ale o różnym zakresie widoczności, którą definiuje użytkownik poprzez deklarację zmiennych w odp. plikach nagłówkowych, które to następnie można inkludować do kolejnych plików źródłowych rozszerzają widoczność na inne moduły.

Definiować zmienne można również w plikach nagłówkowych (nie spowoduje to błędów kompilacji), ale nie jest to zalecenie (silnie niezalecane), bo może powodować lawiny błędów, szczególnie przy rozbudowanych, wieloplikowych projektach.

------------------------ [ Dodano po: 26 minutach ]

mirekk36 napisał(a):

main.c
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Ja bym jeszcze dodał jeszcze, że ten zapis powyższy będzie poprawny tylko i wyłącznie w jakiejś funkcji zdefiniowanej w main.c.
Proszę o komentarz, ja spróbuję tak skomentować.

1. Dostępu do pól struktur nie ma w sekcji zmiennych globalnych. Jedynie podczas definiowania zmiennej można ją zainicjalizować po swojemu:
TMYSTRUCT mojastruktura = {7,2};


2. Zmiennych globalnych nie można inicjować zmiennymi, tylko stałymi. Stąd m.in. częsty błąd podczas kompilacji:
"error: initializer element is not constant."

Oczywiście wymądrzam się, bo sobie zrobiłem projekt i dostałem błędy, a potem wymyśliłem odpowiedź :)



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 10:27 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

Zealota napisał(a):
Zapis ten, wg mnie, sugeruje, że tylko jawna (przez użytkownika) inicjalizacja zmiennej zrobi z tego zapisu definicję
Jeśli nie sugeruje tego autor intencjonalnie, to sam zapis i brak wyjaśnienia mąci innym w głowach, bo faktycznie użytkownik nie musi jawnie inicjować zmiennej, żeby była definicją, zrobi to automatycznie kompilator - bo taki jest standard języka C.


I właśnie na takim czymś - wg takich materiałów uczy się część osób programować w C a później po kilku latach używania tego - jak kolega kisiel - piszą, że tutaj ja opowiadam jakieś bzdury albo swoje zasady na temat języka C

------------------------ [ Dodano po: 5 minutach ]

Zealota napisał(a):
Niestety, jak wiemy z wątku, to bardzo potrzebne "extern" jest najczęściej doklejane przez kompilator jeśli go brakuje w plikach nagłówkowych, stąd mogą rodzić się nieporozumienia.


No tutaj bym tylko doprecyzował , że kompilator nie dokleja extern .... za to próbuje włączać mechanizm "Tentative definitions" czyli próbuje sprawdzać czy pojawiły się aby przypadkiem dwie TAKIE SAME definicje TAKIEJ SAMEJ zmiennej tzn o TAKIEJ SAMEJ nazwie, co więcej sprawdza czy tylko w jednym przypadku zmienna została ew jawnie zainicjalizowana a jeśli tak - to przydzieli w przypadku każdej z tych definicji JEDEN adres w RAM a zatem niejako sklei je w JEDNĄ zmienną. Czyli nie ma to nic wspólnego z doklejaniem extern tak wprost. ALE WARTO wiedzieć jak to działa bo to pozwoli nam często wyszukać jakiś dziwny błąd ....

------------------------ [ Dodano po: 7 minutach ]

Zealota napisał(a):
Powrócę za to jeszcze do rodzaju zmiennych, czy lokalna czy globalna.
Uknułem sobie taką oto skrótową definicję: każda definicja zmiennej wewnątrz funkcji robi z niej zmienną lokalną.
Wszystkie inne definicje (poza funkcjami, również poza main() ) to są zmienne globalne, są bowiem umieszczone w sekcji zmiennych globalnych, ale o różnym zakresie widoczności, którą definiuje użytkownik poprzez deklarację zmiennych w odp. plikach nagłówkowych, które to następnie można inkludować do kolejnych plików źródłowych rozszerzają widoczność na inne moduły.


No i bardzo dobra teoria - chociaż ja również piszę już o tym w Bluebooku ale zrozumiałe jest - że nie od razu czasem wszystko do nas dotrze z jednego źródła - dlatego warto wtedy sięgać również do innych książek - rzadziej tylko do internetu bo jak widać po powyższym twoim przykładzie można w 50% trafić na takie bzdury że szok

------------------------ [ Dodano po: 11 minutach ]

Zealota napisał(a):
Definiować zmienne można również w plikach nagłówkowych (nie spowoduje to błędów kompilacji), ale nie jest to zalecenie (silnie niezalecane), bo może powodować lawiny błędów, szczególnie przy rozbudowanych, wieloplikowych projektach.


Ja bym się z tym nie zgodził - bo wg mnie definiowane zmiennych w plikach *.h to BŁĄD i nie jest to niezalecane - tak się nie robi w C. Oczywiście - jeśli ktoś zrobi to czasem nie wywoła to błędów bo język C nie traktuje tego jako błąd syntaktyczny ale niestety można się do tego przyzwyczaić jak kisiel i weź wtedy po kilku latach wyjaśnij takiej osobie że tak się nie robi - a ona twierdzi że programuje zawodowo od kilku lat więc wie co robi ... Tyle że nie wierzę, że w ciągu tych kilku lat nie pojawiły się problemy przy takim podejściu - ale pewnie były rozwiązywane "na partyzanta" i jakoś tam szło dalej - więc nie znając zasad - można taki błąd wciąż powielać i powielać

krótko - w C nie DEFINIUJE się zmiennych w plikach nagłówkowych

nie definiuje się również funkcji - chociaż tutaj jest pewien wyjątek ;) - otóż można w plikach *.h definiować krótkie funkcje typu inline ;)

------------------------ [ Dodano po: 12 minutach ]

Zealota napisał(a):
Ja bym jeszcze dodał jeszcze, że ten zapis powyższy będzie poprawny tylko i wyłącznie w jakiejś funkcji zdefiniowanej w main.c.
Proszę o komentarz, ja spróbuję tak skomentować.


OCZYWIŚCIE ;) sorki mój błąd - powinienem to był napisać w ramach np funkcji main() i zaraz to na górze poprawię. DZIĘKI za sprostowanie i wskazanie mojego błędu ;)

------------------------ [ Dodano po: 16 minutach ]

Zealota napisał(a):
Oczywiście wymądrzam się, bo sobie zrobiłem projekt i dostałem błędy, a potem wymyśliłem odpowiedź


eeee tam jakie wymądrzanie - mnie osobiście bardzo się podoba tego typu dochodzenie do pewnych wniosków, na forum niewiele osób tak jak ty - testuje pewne rzeczy na żywym organizmie ;) ... tak na gorąco - to chyba przychodzi mi na myśl tu nick kolegi Daro69 - który również dzięki takiemu podejściu - jak ja obserwuję co wyrabia na forum - to BARDZO szybko podnosi swój skill w C ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 11:46 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

A w tzw międzyczasie bo też mam takie zacięcie, żeby wszystko samemu sprawdzić a do tej pory (może wstyd się przyznać) ale nie miałem i nie używałem żadnego kompilatora C na PC pod windowsem, więc nie mogłem do końca sprawdzić np ew różnic w kompilacji pomiędzy tym co opowiadał roske albo kisiel.

Zainstalowałem więc sobie CodeBlocks + kompilator MinGW i stworzyłem identyczny projekt testowy - no i proszę - jeśli w więcej niż jednym pliku inicjalizujemy zmienną "dwa" to KICHA - tu nawet nie zadziała tentative definition, tylko kompilator zwymiotuje błędem "multiple definitions"

zatem zmyślne teorie kolegów roske i kisiel upadają, żeby nie było proszę obrazek. A przy okazji obaj koledzy dowiedzieli się, o co chodzi z tentative definition a jednocześnie mam nadzieję, że zrozumieli jak działa mechanizm zmiennych globalnych w C i jak należy prawidłowo do tego podchodzić.

Obrazek

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 18:20 
Offline
Nowy

Dołączył(a): 01 paź 2017
Posty: 7
Pomógł: 0

mirekk36 napisał(a):
zatem zmyślne teorie kolegów roske i kisiel upadają, żeby nie było proszę obrazek


To samo zaprezentowałem tutaj - zero nowości,
topic19291-30.html#p196297

Czy muszę wspominać również że nigdzie w kodach, które zaprezentowałem nie występuje taka konstrukcja jak definicja 2 tych samych zmiennych w 2 plikach?

------------------------ [ Dodano po: 5 minutach ]

mirekk36 napisał(a):
Ja bym się z tym nie zgodził - bo wg mnie definiowane zmiennych w plikach *.h to BŁĄD i nie jest to niezalecane - tak się nie robi w C. Oczywiście - jeśli ktoś zrobi to czasem nie wywoła to błędów bo język C nie traktuje tego jako błąd syntaktyczny ale niestety można się do tego przyzwyczaić jak kisiel i weź wtedy po kilku latach wyjaśnij takiej osobie że tak się nie robi - a ona twierdzi że programuje zawodowo od kilku lat więc wie co robi ... Tyle że nie wierzę, że w ciągu tych kilku lat nie pojawiły się problemy przy takim podejściu - ale pewnie były rozwiązywane "na partyzanta" i jakoś tam szło dalej - więc nie znając zasad - można taki błąd wciąż powielać i powielać


WEDŁUG CIEBIE - Ale na szczęście to nie Ty definiujesz standard. Reszta to zwykłe oszczerstwa i obrażanie mojej osoby. Nic nie wiesz na temat jakie kody piszę, jak pracuje w grupie ani jak realizuje projekty. Ja w  żadnym poście nie napisałem nic na temat Twojego zachowania, Twojego podejścia do osób, które się z Tobą nie zgadzają. Po prostu skandal i żenada. Tyle ode mnie.



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 19:47 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

kisiel napisał(a):
Myślę że tym programem obaliłem ostatni mit na temat tego że zmienne są globalne tylko w momencie dopisania extern - poniakąd to jest prawda, ale to extern jest niejawnie dopisywane przez kompilator.

Napisałeś bzdurę bo "tentative definition" to nie ŻADNE dopisywanie extern przez kompilator - i żadnego mitu nie obaliłeś, Bo to że kompilator podłoży kilku zmiennym o tej samej nazwie TEN SAM ADRES w ram - NIE MA NIC WSPÓLNEGO ze zmienną globalną. A teksty, że kompilator "łyknie" a tylko kompilator sobie nie radzi to już zupełny odlot.

------------------------ [ Dodano po: kilkunastu sekundach ]

kisiel napisał(a):
Twojego podejścia do osób, które się z Tobą nie zgadzają.

kisiel napisał(a):
Reszta to zwykłe oszczerstwa i obrażanie mojej osoby. Nic nie wiesz na temat jakie kody piszę, jak pracuje w grupie ani jak realizuje projekty. Ja w  żadnym poście nie napisałem nic na temat Twojego zachowania, Twojego podejścia do osób, które się z Tobą nie zgadzają. Po prostu skandal i żenada. Tyle ode mnie.

No no i kot odwrócony ogonem - zostawię to i niech każdy sobie oceni w tym całym wątku co i jak .... tymczasem ja panie kochany, ponieważ dla mnie tajemnica korespondencji mailowej to rzecz święta, nie będę tu przytaczał cytatów z tego co ty do mnie napisałeś na PW i jakie oszczerstwa - i tylko dlatego, że ja się nie zgadzałem z twoim podejściem - napisałem ci na PW, tylko że to co przeczytałem od ciebie w mailu to dziecinada ...

Ja niby źle traktuję osoby które się ze mną nie zgadzają - a jak ty traktujesz takie osoby kochany ? Żegnam cię i życzę ci powodzenia.

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 20:40 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

kisiel napisał(a):
mirekk36 napisał(a):
Ja bym się z tym nie zgodził - bo wg mnie definiowane zmiennych w plikach *.h to BŁĄD i nie jest to niezalecane - tak się nie robi w


WEDŁUG CIEBIE - Ale na szczęście to nie Ty definiujesz standard.

Dobrze byłoby poznać źródło w literaturze tych zdecydowanych twierdzeń.

Próbowałem poszukać jakiegoś podparcia do rozsądzenia tej wątpliwości. Ciężko jest. Oczywiście przeglądnąłem książki, które mam.
Nie znalazłem nic co by potwierdzało Twoją wersję. Być może jestem źle nastawiony, ale jedynie co znalazłem to:
Tomasz Francuz "AVR. Praktyczne projekty"
"Pamiętaj, aby w pliku nagłówkowym nigdy nie umieszczać definicji, powinny tam znajdować się wyłącznie deklaracje.
Nielicznymi wyjątkami są definicje zmiennych typu const oraz krótkich funkcji"
No to Co? Tomasz Francuz też się myli?
Naprawdę trudno zaakceptować Twoje zalecenia, bo niczym tego nie popierasz.

Póki co ja zapamiętuję, żeby NIE UMIESZCZAĆ. Dwa źródła, które znalazłem wskazują jednoznacznie, żeby tego nie robić. Z chęcią poznam jeszcze coś, co temu zaprzecza.

Każdy może sobie wybrać jak pracować, ale w przypadku obwieszczania "w internecie" swoich racji to warto mieć jakieś poparcie.



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 20:45 
Offline
Użytkownik

Dołączył(a): 14 sie 2016
Posty: 905
Pomógł: 39

Chłopaki, dajcie już spokój z tymi kłótniami - niech robią jak chcą, w końcu to oni będą mieli kiedyś problemy.
Dopóki nie uczą innych jest ok ;)

_________________
Moje porady są błędne,nie czytać,zbanować od razu.



Góra
 Zobacz profil  
 
PostNapisane: 4 paź 2017, o 23:44 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27224
Lokalizacja: Szczecin
Pomógł: 1041

roske napisał(a):
Wszystkie zmienne definiowane poza ciałem funkcji opatruje się specyfikatorem 'static', wtedy ich zasięg i widoczność ograniczają się do danej jednostki kompilacji.

A kto mówił inaczej ?

------------------------ [ Dodano po: kilkunastu sekundach ]

roske napisał(a):
W zamieszaniu umknęła wam, ludkowie


a to już TYPOWE chamskie teksty zadętych Śpeców ;) co to obrażają wszystkich - nie mając już żadnych innych argumentów

------------------------ [ Dodano po: 18 minutach ]

roske napisał(a):
Zmienne globalne są gorsze nawet od instrukcji "goto". Naprawdę. I nie wierzcie gdy ktoś, kimkolwiek by nie był, mówi inaczej.

Widzisz roske - przez twoje ZADĘCIE nawet nie zauważyłeś, że ZAWSZE to samo powtarzam ;) ... ale nie ma to jak odkryć koło od nowa ;)

hasta lawista dziecko ;)

------------------------ [ Dodano po: 20 minutach ]

roske napisał(a):
Jedynie naprawdę ważna z wszystkiego co tu powiedziano: zmiennych globalnych się NIE używa.


hahahaha jak się okazało że kolega roske - w końcu zrozumiał co znaczy "tentative definition"

to w końcu zaczyna mówić tym samym językiem ;)

roske
roske napisał(a):
Jedynie naprawdę ważna z wszystkiego co tu powiedziano: zmiennych globalnych się NIE używa.


nie się "NIE" używa - lecz ... panie kochany - ZALECA się nie używać .... ;) a gdzież twoje wcześniejsze bzdury o tym że zmienne globalne to całkiem innego niż opowiadałeś bajki - nie wiedząc co to oznacza: "tentative definition"

------------------------ [ Dodano po: 21 minutach ]

hahahaa nie ma to jak edytować swój post gdy się bzdur nagadało co ? :lol:

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
 
PostNapisane: 5 paź 2017, o 07:46 
Offline
Nowy

Dołączył(a): 01 paź 2017
Posty: 7
Pomógł: 0

Zealota napisał(a):
"Pamiętaj, aby w pliku nagłówkowym nigdy nie umieszczać definicji, powinny tam znajdować się wyłącznie deklaracje.
Nielicznymi wyjątkami są definicje zmiennych typu const oraz krótkich funkcji"


W przytoczonym fragmencie jest napisane że nie powinno się ale skoro są wyjątki, standard to dopuszcza, dopiero DOBRA PRAKTYKA programowania tego zabrania. Ot różnica o którą mi cały czas chodzi.



Góra
 Zobacz profil  
 
PostNapisane: 5 paź 2017, o 09:54 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

kisiel napisał(a):
Zealota napisał(a):
"Pamiętaj, aby w pliku nagłówkowym nigdy nie umieszczać definicji, powinny tam znajdować się wyłącznie deklaracje.
Nielicznymi wyjątkami są definicje zmiennych typu const oraz krótkich funkcji"


W przytoczonym fragmencie jest napisane że nie powinno się ale skoro są wyjątki, standard to dopuszcza, dopiero DOBRA PRAKTYKA programowania tego zabrania. Ot różnica o którą mi cały czas chodzi.


W przytoczonym fragmencie napisane jest "nigdy" i to się tyczy zmiennych, o których rozprawialiśmy w całym tym wątku.
Co prawda za chwilę jest "powinno", więc dość ciężko się zdecydować, być może dlatego później takie dysputy jak nasza ... :)

Nikt z uczestników dyskusji nawet nie wspomniał o przypadku const, prawdopodobnie po prostu nikt tego nie wiedział, na pewno ja nie wiedziałem.
Należało użyć tego argumentu i tyle.

Jeszcze muszę zapytać o "nieużywanie zmiennych globalnych". Sam często spotykam się z taką tezą, ale szczególnie precyzyjnego wyjaśnienia to nie znalazłem.
Wg mnie, dla procesorów AVR, jest to niemożliwe, jeśli korzystamy np z przerwań, gdzie musimy korzystać ze zmiennych globalnych.
No chyba, że można samemu definiować funkcje ISR, tak by podawać dodatkowe parametry - ale czy to nie byłby jakieś nadużycie.



Góra
 Zobacz profil  
 
PostNapisane: 5 paź 2017, o 10:17 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 paź 2014
Posty: 233
Lokalizacja: Rzeszów
Pomógł: 11

Skoro tak rozkładamy te zmienne na czynniki pierwsze, to mam pytanie.

Dlaczego, jeśli zdefiniujemy zmienną globalną np. w projekcie jedno-plikowym typu uint8_t to "Data: 1 bytes" natomiast jeśli tą sama zmienną przy definicji inicjujemy jakąś wartością, to po kompilacji mamy: "Data: 2 bytes" ??? W przypadku zmiennych zajmujących więcej niż jeden bajt już tak nie jest (czy inicjujemy ją czy nie, po kompilacji rozmiar .data odpowiada jej faktycznemu rozmiarowi).

Kolejna sprawa - mechanizm "tentative definition" (tutaj dowiedziałem się, że w ogóle coś takiego jest - nie wiem też czy go dobrze zrozumiałem)- zauważyłem, że gdy w różnych plikach zdefiniujemy trzy takie same zmienne, ale różniące się typem (8, 16 i 32 bity) i ich nie inicjujemy żadną wartością, to kompilator przy .data pokazuje nam wielkość największej z nich (coś ala unia), gdy inicjujemy jedną (Tylko jedną) z nich, to po kompilacji .data pokazuje wielkość tej, którą inicjowaliśmy i wywala wora (nie wywala go, gdy inicjujemy zmienną 16 bitową - jakaś może promocja do int ??? ). Co ciekawe, przy braku inicjacji takich zmiennych, gdy w funkcji nadamy im wartość i przekroczymy zakres (np. w pliku mamy zmienną 8 bitów, wpiszemy 300, lub w innym pliku mamy 16 bitów i wpiszemy 300000) to dostajemy o tym wora. Wygląda to tak, że kompilator rezerwuje miejsce dla największej z nich, a i tak pilnuje ich wielkości w danym pliku.
I jeszcze jeden ciekawy eksperyment - ta sama nazwa zmiennej o różnym rozmiarze w trzech różnych plikach. Inicjujemy tylko tę 16 bitową - brak worningów. W pliku, gdzie zmienna jest 32 bitowa piszemy funkcję, która przypisuje jej wartość 1000000 - poza zakresem zmiennej 16 bitowej. Po kompilacji: ".data 2". Możemy tą funkcję wywołać w main. Zero worningów. Ciekawe, gdzie on zmieści ten 1000000;
Chyba dziś to po testuję na LCD....

I ostatnie pytanie - jeśli w jakimś pliku użyjemy jakiejś nazwy zmiennej (i ją zainicjujemy), to nie możemy jej już użyć nigdzie indziej, mimo, że bez extern nie mamy do niej dostępu. Jak sobie z tym radzą programiści - np. jeden pisze bibliotekę i użyje np. zmiennej licznik, drugi w swojej bibliotece także użyje tej samej nazwy. Trzeci programista połączy te dwie biblioteki i bach - error. Co wówczas? prze-edytować jedną z bibliotek i zmienić nazwy? W definicji jednej ze zmiennych dodać static? Dobrze jak to jest małe, ale jak np. piszą gry (wiem, wiem nie piszą w C, choć nie wiem czy np. w C++ nie jest podobnie) lub inne duże programy.

_________________
Mr. Nobody



Góra
 Zobacz profil  
 
PostNapisane: 5 paź 2017, o 10:49 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

roske napisał(a):
Zealota napisał(a):
Jeszcze muszę zapytać o "nieużywanie zmiennych globalnych". Sam często spotykam się z taką tezą, ale szczególnie precyzyjnego wyjaśnienia to nie znalazłem.


Nie ma dużo do wyjaśniania - tak konstruujesz kod by nie było zmiennych globalnych: wszelkie zmienne zamykasz albo w funkcji z dostępem przez argumenty funkcji i zwracaną wartość albo co najwyżej w ramach modułu (jednostki kompilacji) a dostęp do takich zmiennych robisz przez tzw. settery i gettery.
Przy AVRowych ISR definiujesz zmienne w ramach modułu czyli jako "static volatile". Obejrzyj sobie bibliotekę do UART Petera Fleury, tam jest to bardzo ładnie zrobione.


Niestety nie odpowiedziałeś na moje pytanie. Pytałem dlaczego, a nie jak to zrobić.
No bo oszczędzę pamięć? Czy łatwiej zdebuguję, czy może jeszcze co?



Góra
 Zobacz profil  
 
PostNapisane: 19 gru 2017, o 08:36 
Offline
Użytkownik

Dołączył(a): 18 cze 2015
Posty: 352
Pomógł: 0

Witam
Ponieważ moje zapytanie związane jest z tym tematem, to nie zakładam nowego. W tej kwestii wiele napisano i również wiele
czytałem, ale jak w różnych przypadkach, tak i tutaj pozostaje pewien niedosyt i wątpliwości. Obecnie ćwiczę sobie ustawianie
stanów na porcie C. Podzieliłem sobie projekt na pliki źródłowe i wygląda to następująco:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Program kompiluje się prawidłowo i działa dobrze, ale proszę o wyjaśnienie, czy aby na pewno dobrze napisany. Czytałem, że np.
biblioteka #include <avr/io.h> musi być wszędzie dołączana, ponieważ jest to podstawowa biblioteka C. Ja w main.c mam tylko
#include <util/delay.h>, ponieważ używam po konfiguracji portu. Nie dołączałem biblioteki #include <avr/io.h> ani w main.c
ani w dcba.c. Dopiero jest ona dołączona w dcba.h. Oczywiście dcba.h jest zainkludowana do dcba.c i main.c. Czy tak powinno być,
jak ja napisalem ?. Pytanie to jest w szerszym znaczeniu, ponieważ tyczy się innych plików w podobnych sytuacjach.
Wiem, że zapytanie śmieszne i na bardzo początkującym poziomie, ale bez zrozumienia tego potem same problemy. Oczywiście
inkludowałem przykładową bibliotekę we wszystkich plikach projektu tak dla sprawdzenia, ale niczego to nie wnosi. program i tak
się kompiluje bez problemu, tylko gdzie lezy prawda ?. Jak powinno być.
Proszę o jakieś szersze Wytłumaczenie zasad, jeśli ktoś znajdzie chwilę i chęci. Wiem, że w BB jest i czytałem, ale każdy chwyta
inaczej... Pozdrawiam.



Góra
 Zobacz profil  
 
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Ten wątek jest zablokowany. Nie możesz w nim pisać ani edytować postów.  [ Posty: 64 ]  Przejdź na stronę Poprzednia strona  1, 2, 3  Następna strona

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO