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



Teraz jest 19 lip 2018, o 10:54


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ę 1, 2, 3  Następna strona
Autor Wiadomość
PostNapisane: 30 wrz 2017, o 06:30 
Offline
Użytkownik
Avatar użytkownika

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

mam pytanie w temacie podziału na pliki, do kodu z książki , projekt multipleksowania led , czemu

Kod:
volatile uint8_t cy1;
volatile uint8_t cy2;
volatile uint8_t cy3;
volatile uint8_t cy4;


definicjie zmiennych globalnych są umieszczone w pliku d_led.c a nie nad main w pliku main.c czemu? ,

w takim razie jak to rozumieć kompilator startując dokleja zaczynając od main.c i kolejne pliki .c w jeden wielki plik .c , taki plik dziwnie wyglądałby z definicjami zmiennych globalnych gdzieś w połowie. ;)

tak przed chwilą to przeniosłem definicjie z pliku d_led.c do pliku main.c i działa , jaka więc różnica czemu pisze się tak a nie tak ?

Jeśli umieścić definicjię zmiennej globalnej nad funkcją main to po co umieszczać jej deklaracjie w pliku nagłówkowym i dołączać, definicja to przecież jednocześnie deklaracja .



Góra
 Zobacz profil  
 
PostNapisane: 30 wrz 2017, o 06:46 
Offline
Użytkownik

Dołączył(a): 25 lip 2013
Posty: 1472
Pomógł: 73

Oglądnij filmik Mirka



Góra
 Zobacz profil  
 
PostNapisane: 30 wrz 2017, o 07:13 
Offline
Użytkownik
Avatar użytkownika

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

;) Aha okej już ogladam



Góra
 Zobacz profil  
 
PostNapisane: 30 wrz 2017, o 08:18 
Offline
Użytkownik
Avatar użytkownika

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

Nie znalazłem tam odpowiedzi na moje pytanie tzn. poradnik świetny ale nie ma w nim opisanego postępowania ze zmiennymi globalnymi .

Wydaje mi się że definicjie zmiennych globalnych można umieścić w każdym pliku źródłowym projektu i tak będzie prawidłowo .



Góra
 Zobacz profil  
 
PostNapisane: 30 wrz 2017, o 09:08 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 29 mar 2012
Posty: 539
Lokalizacja: Jaworzno
Pomógł: 32

Te zmienne dotyczą bezpośrednio sterowania wyświetlaczem LED(warstwy sprzętowej), dlatego jeżeli mamy wydzieloną bibliotekę do obsługi wyświetlacza to na logikę powinny być umieszczone w pliku bibliotecznym. Po co takie zmienne mają się plątać gdzieś po main.c i zaśmiecać kod programu głównego? Druga sprawa, zauważ że te zmienne są użyte w przerwaniu Timera. Funkcja obsługi przerwania jest umieszczona w pliku bibliotecznym d_led.c.

_________________
Pozdrawiam



Góra
 Zobacz profil  
 
PostNapisane: 30 wrz 2017, o 09:26 
Offline
Moderator
Avatar użytkownika

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

Piotrek_P napisał(a):
Te zmienne dotyczą bezpośrednio sterowania wyświetlaczem LED(warstwy sprzętowej), dlatego jeżeli mamy wydzieloną bibliotekę do obsługi wyświetlacza to na logikę powinny być umieszczone w pliku bibliotecznym. Po co takie zmienne mają się plątać gdzieś po main.c i zaśmiecać kod programu głównego? Druga sprawa, zauważ że te zmienne są użyte w przerwaniu Timera. Funkcja obsługi przerwania jest umieszczona w pliku bibliotecznym d_led.c.

Nic dodać nic ująć

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

procek87 napisał(a):
Wydaje mi się że definicjie zmiennych globalnych można umieścić w każdym pliku źródłowym projektu i tak będzie prawidłowo .

Masz rację, wydaje ci się ....

Bo ty wciąż patrzysz z punktu widzenia programowania chyba w Bascomie albo andruino gdzie zwykle każdy pisze program w JEDNYM GIGANTYCZNYM pliku ...

Język C daje zaś ogromne możliwości pięknego podziału kod na LOGICZNE bloki (czyli pliki) ... I teraz gdy chcesz używać zmiennych cy1,cy2,cy3, cy4 w jakimś innym pliku projektu

to łatwo się domyśleć, że wystarczy zainkludować plik d_led.h

a jeśli umieścisz te zmienne w main.c .... i zechcesz ich później używać chociażby w d_led.c (BO TAM ICH UŻYWANIE JEST PODSTAWOWE) to co ? jak będziesz to inkludował - oczywiście teraz ci przez PRZYPADEK działa gdy przeniosłeś ich definicje do main.c ponieważ jak widać kompletnie nie rozumiesz co to są z kolei DEKLARACJE zmiennych, które pozostawiłeś nieruszone w d_led.h

Oczywiście tak to działa - ale teraz sobie wyobraź, że masz projekt składający się ze 120 plików ... i co? gdy za rok będziesz chciał dostać się do definicji jakiejś zmiennej to co? Będziesz szalał szukając ich po wszystkich plikach bo zapomniałeś gdzie dałeś tak ?

Gdy tymczasem wiadomo, że jak się LOGICZNIE podzieli projekt - to nawet bez szukania będzie można się domyśleć wręcz, że zmienne buforowe dla cyfr wyświetlacza LED tzn ich DEFINICJE zapewne są w pliku d_led.c

Natomiast gdyby zrobić to po twojemu - że umieścisz je w main.c i dodasz tam jeszcze zmienne ze 120 innych plików projektu to będziesz miał BONANZĘ NA KÓŁKACH - żeby delikatnie to jakoś określić

Nie wspomnę już - że coś czuję że w ogóle nie przeczytałeś rozdziału w Bluebooku na temat podziału projektu na pliki - bo gdybyś przeczytał - i nawet nie zrozumiał do końca - co bywa oczywiste gdy ktoś się uczy, że czegoś nie zrozumie - to już dawno zadałbyś pytanie do tego co w książce żeby sobie coś doprecyzować

Dlatego nie wymyślaj koła od nowa - tylko zajrzyj do książki, przeczytaj - potem dopiero obejrzyj poradnik który polecił ci kolega micky (słusznie zresztą) to wtedy okaże się, że go zrozumiesz tzn ten poradnik, i że ci jednak dodatkowo coś podpowie - że znajdziesz to czego szukasz

_________________
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: 1 paź 2017, o 06:46 
Offline
Użytkownik
Avatar użytkownika

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

przeczytałem już 5 razy ten rozdział a poradnik na youtube to chyba 3 oglądnełem, jak będzie trza to i następnych 20 razy w końcu zrozumie :)

Pytanie, które mi się nasunęło dotyczy znowu zmiennych globalnych i funkcji ,

Po co w ogóle poprzedzać definicje takiej zmiennej
Kod:
static  uint8_t kow;
by ta stała się widoczna tylko w pliku, w którym jest zdefiniowana , skoro można poprostu nie wrzucać do pliku nagłówkowego deklaracji takiej zmiennej poprzedzonej
Kod:
extern uint8_t kow;
i efekt będzie taki sam zmienna będzie widoczna tylko w ramach jednego pliku.



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

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

znalazłem post z odpowiedzią , ale jeśli ktoś coś opowie to będzie super, jednak

potrzebuje przykładów inaczej nie za trybie.



Ostatnio edytowano 4 paź 2017, o 20:12 przez procek87, łącznie edytowano 1 raz

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

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

przeczytaj rozdział w Bluebooku o zmiennych statycznych wewnątrz funkcji i wtedy jak czegoś nie zrozumiesz to zadaj pytanie - bo mi ciężko tu powtarzać to samo co w książce

_________________
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: 1 paź 2017, o 12:40 
Offline
Użytkownik
Avatar użytkownika

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

zadam pytanie w odniesieniu do str 134 , rozdz 3.5.6 "Funkcje w różnych plikach projektu" no i rozdziału wcześniej o zmiennych i funkcjach statycznych ,

zauważyłem że dzieląc projekt na pliki jeśli chce się ukryć przed innymi plikami projektu zmienną globalną czy też funkcje dodaje się static przed definicją i usuwa jej deklaracje w pliku nagłówkowym wtedy jej widoczność określa się tylko dla tego pliku w którym jest ona zdefiniowana,

jeśli chce się by były widoczne pisze się ich definicje bez static z wyciągniętą deklaracją do pliku nagłówkowego pliku źródłowego z extern .

w projekcie jedno plikowym z jednym tylko main.c nie ma takiej potrzeby dlatego definicje zmiennych globalnych nie poprzedza się static bo też do jakiego pliku miała by się odnieść, można dołączyć tylko plik nagłówkowy .h w którym można zawrzeć definicje dla preprocesora makra #define.

Jeśli coś knocę to poprawcie ;)



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

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

no i bardzo ładnie to opisałeś

Ja tylko uzupełnię, że słówko static nie służy do UKRYWANIA i ma na dodatek nieco inne znaczenie w przypadku zmiennych globalnych i lokalnych.

specyfikator static powoduje, że mówisz kompilatorowi - ZRÓB PAN sobie co chcesz w procesie optymalizacji bo mi nie zależy żeby ta zmienna czy funkcja była widoczna w innym module ... Wtedy kompilator może funkcje ze specyfikatorem static czasem potraktować jako inline a często ich widok w asemblerze będzie mocno zmieniony niż gdyby były kompilowane bez static.

No i doczytaj sobie co to takiego static dla zmiennych automatycznych/lokalnych - czyli definiowanych wewnątrz funkcji - że zachowują się wtedy jak globalne ale widoczne są tylko dla tej funkcji

_________________
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: 1 paź 2017, o 13:43 
Offline
Użytkownik
Avatar użytkownika

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

dla zmiennych lokalnych stosowanie static ma inne znaczenie tak wiem taka zmienna z static zamienia się w zmienną globalną tylko tyle że widoczność ma lokalną.

staram się tak pytać i opowiedzieć poniekąd by ktoś przecierający tą drogę, następny początkujący jak ja miał łatwiej , a książkę czytam już któryś raz i za każdym razem dowiaduje się czegoś nowego, ale wiadomo warto. ;)



Ostatnio edytowano 1 paź 2017, o 17:23 przez procek87, łącznie edytowano 1 raz

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

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

procek87 napisał(a):
staram się tak pytać i opowiedzieć

no i to rozumiem - bo mi też łatwiej wtedy coś ew doprecyzować, wyjaśnić szerzej itp

_________________
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: 1 paź 2017, o 19:33 
Offline
Użytkownik
Avatar użytkownika

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

kolejne pytanie w pliku main.c projektu 03_Multi_LED w pętli while rozbiłeś liczbę wyświetlaną na tysiące, setki,dziesiątki, jednostki , czy można zawartość tej pętli umieścić w jakiejś funkcji , wywoływać z while w main ,

funkcje zamknie się w pliku no i właśnie Mirku czy według Ciebie dobrym nawykiem będzie dodanie jej do pliku d_led.c odpowiedzialnego za inicjalizacjie wyświetlacza czy wydzielić ją w osobnym pliku,

------------------------ [ Dodano po: 8 minutach ]

Cytuj:
Nie będzie taki sam. Zmienne globalne domyślnie są widoczne w całym programie. Deklaracja ze słowem kluczowym extern nic tu nie zmienia, a potrzebna jest jedynie dla wskazania typu zmiennej.


kolego Roske myślę że się mylisz zmienna globalna domyślnie jest widoczna w ramach jednego pliku nie programu a deklaracja zmiennej globalnej z magicznym słowem extern oznacza nie definicjie a deklaracje ,wiadomość dla kompilatora o istnieniu takiej definicji gdzieś tam w plikach programu.



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

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

roske napisał(a):
Nie będzie taki sam. Zmienne globalne domyślnie są widoczne w całym programie. Deklaracja ze słowem kluczowym extern nic tu nie zmienia, a potrzebna jest jedynie dla wskazania typu zmiennej.

No tu to kolega widać, że jeszcze kompletnie nie rozumie o co chodzi przede wszystkim z DEFINICJĄ i DEKLARACJĄ zmiennej, nie wie do czego jest słówko kluczowe extern, no i hmmm nie orientuje się co do zakresu widoczności.

Ciężko znowu i od nowa to samo powtarzać, ale żeby nie było że tylko coś przygadałem i poszedłem no to doprecyzuję.

Panie kochany - zmienne GLOBALNE nie są domyślnie widoczne w całym programie - no chyba że ty masz na myśli projekt składający się z jednego pliku main.c. Jeśli projekt składa się z wielu plików to szanowny kolego - zmienna zdefiniowana w jednym z takich plików NIGDY W ŻYCIU nie będzie widoczna w innym. Zrozum to. Stanie się tak dopiero jeśli w innym pliku zainkludujesz plik *.h w którym będzie (Uważaj teraz) DEKLARACJA takiej zmiennej - a uzyskać to można w przypadku zmiennych TYLKO I WYŁĄCZNIE za pomocą specyfikatora "extern"

zaś typ zmiennej określa jej TYP po lewej stronie w DEFINICJI ;)

------------------------ [ Dodano po: 8 minutach ]

procek87 napisał(a):
kolejne pytanie w pliku main.c projektu 03_Multi_LED w pętli while rozbiłeś liczbę wyświetlaną na tysiące, setki,dziesiątki, jednostki , ... ,


ale zrozum, że ja w plikach main.c chcę tylko w jakikolwiek sposób pokazać jak się korzysta z bibliotek które omawiam. Poza tym w tym konkretnym przypadku z tym wyświetlaniem liczby - to ot tak na gorąco chciałem pokazać po prostu jeden z bardzo wielu sposobów jak matematycznie izolować KAŻDĄ pojedynczą cyfrę z dłuższej liczby ;)

procek87 napisał(a):
czy można zawartość tej pętli umieścić w jakiejś funkcji , wywoływać z while w main ,
funkcje zamknie się w pliku


no pewnie, że można - a nawet warto wydzielać funkcje - to zawsze jest najlepsza droga - nie zaś ładować KUPĘ kodu w głównej pętli programu - ale musisz też zrozumieć pewien proces dydaktyczny którym ja idę - nie jestem w stanie w tej książce od razu tego pokazać - bo byłoby to niezrozumiałe.

procek87 napisał(a):
czy według Ciebie dobrym nawykiem będzie dodanie jej do pliku d_led.c odpowiedzialnego za inicjalizacjie wyświetlacza czy wydzielić ją w osobnym pliku,

dla mnie konieczność tworzenia nowego pliku projektu pojawia się głównie wtedy gdy ma w nim być więcej niż jedna funkcja - a szczególnie gdy te funkcje mają być wywoływane z innych plików projektu

Tymczasem w tak MEGA PROSTYM przykładzie dość ciężko nawet rozpatrywać czy wydzielać do oddzielnego pliku funkcję odpowiedzialną za wyświetlanie tej liczby ...

ale rozumiem co masz na myśli i jeśli np chciałbyś stworzyć jakąś uniwersalną funkcję do wyświetlania dowolnej liczby na wyświetlaczu LED to oczywiście masz BARDZO dobry pomysł, żeby wtedy taką funkcję dodać nawet do pliku d_led.c ponieważ wtedy ładnie rozbuduje się biblioteka do obsługi wyświetlacza, i będziemy mieli np:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


wtedy zamiast w pętli głównej robić tą rozbiórkę - będzie ona ładnie schowana w d_led.C zaś w pętli głównej będzie sobie tylko zapierniczał licznik i co chwilę będzie wywoływana funkcja np:

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: 1 paź 2017, o 20:32 
Offline
Użytkownik
Avatar użytkownika

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

Roske wszystko masz w BB szukanie info po wikipedia mija się z celem w książce masz twarde info trza czytać i pytać:)



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

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

roske napisał(a):
W tych czasach niemal wszystkie informacje można łatwo zweryfikować. Pierwszy wynik z googla:
"Global variables in C are by default extern.. (i.e) they have external linkage.."
W kolejnym wyniku trochę szerzej, nie będę przepisywał oto link:
https://stackoverflow.com/questions/423 ... tic-or-not
Wpis w wikipedii jeszcze to rozszerza:
https://en.wikipedia.org/wiki/Global_va ... nd_C.2B.2B
No i na koniec cytat z Kernighan, Ritchie "Język C" (Zwracam uwagę na fragment w nawiasie):
"Przez domniemanie zmienne zewnętrzne są także "globalne", a więc wszystkie odwołania do takiej zmiennej przez tę samą nazwę (nawet z funkcji tłumaczonych oddzielnie) są odwołaniami do tego samego obiektu"


kolega widzę mocno nie rozumie co znaczy GLOBALNE ;) ja nawet nie będę dyskutował o linkach na stackoverflow bo szkoda

już prędzej odniosę się do porządnego źródła dla ciebie czyli

Cytuj:
cytat z Kernighan, Ritchie "Język C" (Zwracam uwagę na fragment w nawiasie):


to ja ci powiem, że ty musisz bardziej zwracać uwagę ... bo w książce jest DOBRZE - zmienna globalna jest GLOBALNA w ramach tego samego ale JEDNEGO pliku projektu (źródłowego pliku *.c) - i ty tego wydaje mi się kompletnie nie rozumiesz

ale to wynika zapewne z tego, że nie wiesz jak w języku C przebiega proces kompilacji - obejrzyj sobie to:
https://www.youtube.com/watch?v=FfL-Zj_RHeY

może to ci więcej rozjaśni ....

A wtedy zrozumiesz dlaczego jest specyfikator "extern" dzięki któremu możemy spowodować, że gdy go użyjemy ale uwaga w plikach nagłówkowych *.h to stworzymy DEKLARACJĘ zmiennej .... to z kolei spowoduje, że przy kompilacji kompilator zarezerwuje sobie adres na zmienną o wielkości jej typu, natomiast reszty dokończy jeden z ostatnich etapów czyli linker łączący wstępnie skompilowane pliki *.c do postaci *.o - w jeden wynikowy plik HEX albo BIN

i tak jak kolega wyżej napisał - masz to wszystko w Bluebooku

_________________
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: 1 paź 2017, o 22:03 
Offline
Nowy

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

Witam,
forum czytuje sporadycznie, ale nie zrozumiałem jednej z Twoich wypowiedzi:

Cytuj:
Stanie się tak dopiero jeśli w innym pliku zainkludujesz plik *.h w którym będzie (Uważaj teraz) DEKLARACJA takiej zmiennej - a uzyskać to można w przypadku zmiennych TYLKO I WYŁĄCZNIE za pomocą specyfikatora "extern"



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

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

kisiel napisał(a):
Witam,
forum czytuje sporadycznie, ale nie zrozumiałem jednej z Twoich wypowiedzi:

Cytuj:
Stanie się tak dopiero jeśli w innym pliku zainkludujesz plik *.h w którym będzie (Uważaj teraz) DEKLARACJA takiej zmiennej - a uzyskać to można w przypadku zmiennych TYLKO I WYŁĄCZNIE za pomocą specyfikatora "extern"


Chodzi o to, że aby zmienna globalna mogła być widoczna w innych plikach to trzeba powołać jej DEKLARACJĘ, a to oznacza wpisanie do pliku *.h (który będzie inkludowany tam gdzie potrzeba - czyli w różnych plikach *.c) specyfikatora "extern" a po nim typu i nazwy zmiennej ale już bez jej inicjalizacji, a w przypadku tablicy bez podawania ile ona ma elementów.

Przykład:

jakiś plik źródłowy *.c z DEFINICJAMI zmiennych

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



stworzony plik nagłówkowy *.h z DEKLARACJAMI zmiennych

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: 2 paź 2017, o 08:23 
Offline
Tech-support
Avatar użytkownika

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

Ja jeszcze chciałbym się odnieść do tego fragmentu:
roske napisał(a):
Przez domniemanie zmienne zewnętrzne są także "globalne", a więc wszystkie odwołania do takiej zmiennej przez tę samą nazwę (nawet z funkcji tłumaczonych oddzielnie) są odwołaniami do tego samego obiektu
Moim zdaniem oznacza to, że zmienne zewnętrzne są traktowane jak globalne. Natomiast nie działa to w drugą stronę, czyli zmienne globalne niekoniecznie są zewnętrzne.

To trochę tak, jakbyś powiedział, że "wszystkie kwadraty są rombami". Ale czy to znaczy, że wszystkie romby są kwadratami?



Góra
 Zobacz profil  
 
PostNapisane: 2 paź 2017, o 08:56 
Offline
Nowy

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

Czyli jeżeli dobrze rozumiem. Jak nie dam extern w pliku *.h to zmienna nie będzie widoczna w innych plikach, nawet jeżeli plik nagłówkowy będzie zincludowany w innym pliku?



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

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

roske napisał(a):
Zamiast bicia piany

Po pierwsze proponuję zejście o ton niżej, chyba że szanowny kolega chce sobie w ten sposób dyskutować na innym forum ...

roske napisał(a):
zmienna "jeden" zdefiniowana w pliku "foo.c", a następnie zainkludowana przez deklarację z modyfikatorem extern w "foo.h" do pliku "main.c" jest zmienną globalną widoczną w całym programie. Zmienna dwa zdefiniowana w pliku "foo.c", nie jest zainkludowana do "main.c" z modyfikatorem extern więc jej zasięg ogranicza się do pliku "foo.c". Zmienna "dwa" zdefiniowana w pliku "main.c" o przypadkowo tej samej nazwie jest całkiem inną zmienną niż ta zdefiniowana w "foo.c", jej widoczność ogranicza sie tylko do pliku "main.c". Odwołania do zmiennej "dwa" w plikach "main.c" i "foo.c" są odwołaniami do dwóch różnych obiektów.


I co to ma oznaczać wg ciebie ? Toż ZDEFINIOWAŁEŚ w dwóch plikach dwie zmienne o takiej samej nazwie ! Oznacza to, że nazwy się pokrywają, pisząc to napisałeś pokazujesz z kolei że chyba nie wiesz co to oznacza "zasięg zmiennych / przesłanianie nazw". Twój cały rozbudowany przykład można sprowadzić do bardzo prostego:


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


jak myślisz jaka liczba się ukaże w wyniku tego ? oczywiście 200 i nic w tym dziwnego ponieważ zakres widoczności zmiennej będzie działać zawsze na korzyść zmiennej lokalnej funkcji albo pliku.

Natomiast twój przykładowy kod zawiera PASKUDNE błędy - dlaczego? Dlatego właśnie, że w obszarze zmiennych globalnych każdego modułu ZDEFINIOWAŁEŚ wielokrotnie zmienną o nazwie dwa. Zrób sobie prosty test, dodaj trzeci moduł projektu, tzn kolejną parę plików *.c i *.h i zrób to samo czyli w trzecim również spróbuj zdefiniować zmienną o nazwie dwa i zobacz czy ci się to skompiluje ....

albo ... np usuń definicję int dwa; ze swojego main.c .... i co? uda się kompilować ? ... no nie uda się ;) ... jeśli zaś dodasz w pliku foo.h DEKLARACJĘ ZMIENNEJ czyli

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


to wtedy kompilacja się powiedzie

_________________
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 10:35 
Offline
Nowy

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

Napisałem taki 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.


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.


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.


Pomijam fakt totalnego braku enkapsulacji, co jest wręcz rzeczą niedopuszczalną przy pisaniu niezależnego modułu. Ale jak widać, zmienna, która została zdeklarowana w pliku module.h jak i zmienna_extern, są widoczne we wszystkich plikach, w jakich występuje

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


Także zmienne globalne, to zmienne globalne i tyle. Myślę że tym przykładem wyjaśniłem temat używania extern'a podczas programowania w języku C. Słowo extern należy zamienić na zestaw getterów oraz setterów dla danego modułu aby wpajać już od początków przynajmniej podstawy eknapsulacji modułu.

Pozdrawiam



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

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

roske napisał(a):
Jeśli tak to zdaje się, że właśnie potwierdziłeś to co napisałem kilka postów wcześniej:

Nie potwierdziłem, wręcz odwrotnie - proszę spróbuj usunąć definicję "dwa" z main.c i powiedz czy definicja "dwa" istniejąca w obszarze zmiennych globalnych modułu foo.h - rozprzestrzeni się samoistnie do pliku main.c

zrób ten prosty test - później porozmawiamy dalej i doprecyzujemy

------------------------ [ Dodano po: 3 minutach ]

kisiel napisał(a):
zmienna, która została zdeklarowana w pliku module.h

mylisz pojęcia,

w pliku *.h dokonałeś DEFINICJI zmiennej - czego się nie robi w języku C a drugi zapis ze specyfikatorem extern to DEKLARACJA - sorki ale wydaje mi się, że właśnie koledzy nie do końca rozumieją różnicę pomiędzy DEFINICJĄ a DEKLARACJĄ zmiennej i stąd takie pomysły - bo bo ten pomysł

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


bije już na głowę wszystko ... jeszcze raz podkreślam. W języku C nie robimy DEFINICJI zmiennych w plikach nagłówkowych - a jeśli ją tak zrobisz to owszem zadziała ale w przyszłości sporo sobie namieszasz takim podejściem bo wiesz - są i tacy co np inkludują pliki źródłowe i piszą, że im to zadziałało - to znaczy, że tak można w C. Można ? ;)

_________________
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 11:02 
Offline
Nowy

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

Kto nie rozumie co to jest deklaracja? Po pierwsze, deklaracja jest w momencie kiedy zmienna posiada typ oraz nazwę i NIE WAŻNE gdzie wpiszemy tą deklaracje, czy w pliku *.h czy w pliku *.c - to nadal jest DEKLARACJA. Definicja zmiennej następuje, kiedy do zmiennej przypisujemy jakąś wartość.

Chciałbym zapoznać się z miejscem w standardzie opisującym język C, mówiącym o tym że w tymże języku nie ma żadnej możliwości DEKLARACJI zmiennej. Jeżeli zaś, mówimy o tym że w przyjętym sposobie programowania nie używa się metody DEKLARACJI zmiennej w plikach nagłówkowych, to z tym nie będę dyskutować.

mirekk36 napisał(a):
bije już na głowę wszystko ... jeszcze raz podkreślam. W języku C nie robimy DEKLARACJI zmiennych w plikach nagłówkowych - a jeśli ją tak zrobisz to owszem zadziała ale w przyszłości sporo sobie namieszasz takim podejściem bo wiesz - są i tacy co np inkludują pliki źródłowe i piszą, że im to zadziałało - to znaczy, że tak można w C. Można ? ;)


Jak pierwsza część to totalna bzdura, bo specyfika języka C nijak nie zabrania takich rzeczy, to już druga część potwierdza jedynie moje słowa o enkapsulacji, co automatycznie każe zastanowić się programiście nad tym czy warto w takim razie dodawać do każdej zmiennej (notabene jeżeli nie jest ona poprzedzona słowem static, to jest ona z automatu extern) słowa "extern", co sprowadza znów do tego że w kodzie jest śmietnik ;)

http://www.open-std.org/jtc1/sc22/wg14/ ... /n1124.pdf
I żeby nie było że jestem gołosłowny - w podanym linku standard języka C mówi
Cytuj:
6.2.2 Linkages of identifiers:
For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.


Chciałbym też nadmienić że nie jestem jakiś tam pierwszy lepszy szaraczek, tylko programowaniem w C zajmuje się zawodowo już od paru lat. Czekam na merytoryczne ustosunkowanie się do standardu C :)

Pozdrawiam

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

Dla potwierdzenia moich słów przeprowadziłem drugi test:

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.


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.


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.


wynik:
Kod:
zmienna bez extern: 0                                                                                                                                                                                                                                                                                                       
zmienna z extern: 15                                                                                                                                                                                                                                                                                                         
zmienna bez extern: 5                                                                                                                                                                                                                                                                                                       
zmienna z extern: 6 


Dla wszystkich tych, co chcą przetestować czy to działa czy nie, krótka instrukcja kompilacji z konsoli linuxowej:
1. Tworzymy katalog
2. Wrzucamy tam pliki
3. Wywołujemy polecenie:
Składnia: [ Pobierz ] [ Ukryj ]
język bash
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Pozdrawiam



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

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

roske napisał(a):
Oczywiście, że się "rozprzestrzeni", ale kompilator zgłosi błąd ponieważ nie będzie znał typu zmiennej.

No w tym momencie sam sobie zaprzeczasz i twierdzisz, że jest OK ? Skoro zgłosi błąd to chyba nie będzie za dobrze hmmm ?

roske napisał(a):
Proponuję Ci jednak skompilować i uruchomić choćby tylko mój pierwszy programik main.c/foo.c/foo.h,

Nie zdziwię się, bo ja kompilowałem a ty kompletnie nie odniosłeś się do tego co pisałem i prosiłem żebyś sprawdził ...

kisiel napisał(a):
Kto nie rozumie co to jest deklaracja?

No ty nie rozumiesz, tak mi się wydaje.

kisiel napisał(a):
Po pierwsze, deklaracja jest w momencie kiedy zmienna posiada typ oraz nazwę i NIE WAŻNE gdzie wpiszemy tą deklaracje, czy w pliku *.h czy w pliku *.c - to nadal jest DEKLARACJA. Definicja zmiennej następuje, kiedy do zmiennej przypisujemy jakąś wartość.

Przepraszam cię najmocniej ale nawet pomimo tego co napisałeś niżej:

kisiel napisał(a):
Chciałbym też nadmienić że nie jestem jakiś tam pierwszy lepszy szaraczek, tylko programowaniem w C zajmuje się zawodowo już od paru lat

Co widać zresztą po wypowiedziach, jakbyś połknął wszystkie rozumy świata - to ja ci tylko podpowiem, że ja jestem początkujący w języku C - to tak żebyśmy się rozumieli ok? Ja pisząc, dyskutując też się uczę .... ale jeszcze raz powtórzę - to co napisałeś

kisiel napisał(a):
Po pierwsze, deklaracja jest w momencie kiedy zmienna posiada typ oraz nazwę i NIE WAŻNE gdzie wpiszemy tą deklaracje, czy w pliku *.h czy w pliku *.c - to nadal jest DEKLARACJA. Definicja zmiennej następuje, kiedy do zmiennej przypisujemy jakąś wartość.

to jest wierutna BZDURA niestety. Ba, to co napisałeś pokazuje nawet, że ty chyba nie wiesz (tak się domyślam tylko), że np zmienne globalne są automatycznie inicjalizowane wartością = 0, więc gdybyś o tym wiedział to nie pisałbyś bzdur, że z definicją mamy do czynienia tylko wtedy gdy przypisujemy do niej jakąś wartość .... BZDURA NAD BZDURY!

przepraszam walnąłem się bo miałeś plik *.C już mi się miesza w oczach zaraz odpiszę na dalszą część inaczej

------------------------ [ Dodano po: 23 minutach ]

jeśli mam plik 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.

to szanowny kolego pokazałem ci co to jest DEFINICJA zmiennej. Definicja oznacza, że kompilator zarezerwuje dla tej zmiennej od razu DWA bajty ponieważ mamy typ int (a ja podaję przykłady dla AVR GCC) .... I tym się charakteryzuje DEFINICJA zmiennej, nie ważne czy na procka czy na PC. Po kompilacji zobaczysz zajętość pamięci RAM = 2 bajty.
Cytuj:
Device: atmega32

Program: 132 bytes (0.4% Full)
(.text + .data + .bootloader)

Data: 2 bytes (0.1% Full)
(.data + .bss + .noinit)


A teraz uważaj panie kolego, zrób taki test:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


no i teraz zobacz na zajętość pamięci RAM:
Cytuj:
Device: atmega32

Program: 116 bytes (0.4% Full)
(.text + .data + .bootloader)

Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)


widzisz sekcję DATA? = 0 bytes

I ja dobrze rozumiem skąd programiści C nawet jak piszesz programujący od kilku lat na PC mają problem ze zrozumieniem tych zagadnień, a to dlatego, że nigdy nie patrzą na to pod kątem zajętości pamięci - co się dzieje po kompilacji - to zwykle na PC jest mało ważne - a wtedy pojawiają się takie dziwne pomysły jak twoje.

Podsumowując jeśli dołączysz do projektu plik foo.h w którym napiszesz

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


bez specyfikatora extern, to zrozum, że to będzie DEFINICJA zmiennej abc i to w KAŻDYM pliku źródłowym do którego zainkludujesz taki plik *.h. A to, że będziesz widział zawartość zmiennej abc z pliku main.c - to co opowiada z kolei roske - to dlatego, że linker przyjmie adres zmiennej w pamięci RAM zdefiniowanej w pliku main.c i nie ma w tym nic dziwnego dokąd nie stworzysz dotatkowych plików i wtedy kompilator zacznie się drzeć, że błąd ponieważ widzi

multiple definition of abc;
-------------------------------------------------------------

a więc tak, twój przykładowy program main.c zostanie w procesie prekompilacji za pomocą PREPROCESORA rozwinięty do takiej postaci (teraz uważaj dokładnie)

kisiel napisał(a):
Dla potwierdzenia moich słów przeprowadziłem drugi test:


to raczej dla potwierdzenia że niestety kompletnie nie rozumiesz o co chodzi, już wyjaśniam - to co zrobiłeś ;) ten program który napisałeś rzekomo dla potwierdzenia - po wstępnej fazie kompilacji przez PREPROCESOR o czym też zdajesz się nie wiedzieć będzie wyglądał TAK (zdziwisz się pewnie teraz)

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


czyli krótko do:

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


i dzięki temu, że robisz bzdurę i w pliku *.h robisz DEFINICJĘ zmiennej - to DLATEGO w tak prostym projekcie zadziałało to u ciebie

a teraz jak mówię dodaj trzeci plik *.c i zainkluduj swój plik *.h - OOOOOJ BĘDZIESZ ZDZIWIONY - bo się nie skompiluje a ty zobaczysz błąd

multiple definitions

_________________
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 12:13 
Offline
Użytkownik
Avatar użytkownika

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

kisiel napisał(a):
Dla wszystkich tych, co chcą przetestować czy to działa czy nie, krótka instrukcja kompilacji z konsoli linuxowej:
1. Tworzymy katalog
2. Wrzucamy tam pliki
3. Wywołujemy polecenie:
Składnia: [ Pobierz ] [ Ukryj ]
język bash
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Pozdrawiam


mirekk36 napisał(a):
Nie zdziwię się, bo ja kompilowałem a ty kompletnie nie odniosłeś się do tego co pisałem i prosiłem żebyś sprawdził ...


No chyba jednak Kolega kisiel nie sprawdza tego co pisze.

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


będzie oczywiście warning:
"main.c: In function ‘main’:
main.c:16:5: warning: implicit declaration of function ‘init’ [-Wimplicit-function-declaration]
init();
^"
bo zabrakło deklaracji funkcji w pliku nagłówkowym.

Wiem, że to nie cel tego ćwiczenia, ale chyba powinniśmy w każdym momencie pisać zgodnie z zasadami.
Bo jeśli ktoś tak nie pisze, a potem powołuje się na swoje doświadczenie to traci tylko na wiarygodności.

Zresztą jeszcze do jednego można się przyczepić, ale poprawcie mnie jeśli się mylę:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


powinno wyglądać:

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


Pewnie ten void to szczegół, ale chyba dobre praktyki programowania "zalecają" by o tym pamiętać.

Czy to "wymuszenie" nie zabezpieczy nas przed błędami np przy przenoszeniu kodu?

A może po prostu się czepiam? Może to są nieistotne szczegóły?
A może w tzw "zawodowym programowaniu" to już się nie patrzy na takie drobiazgi?

Ja u siebie staram się wszystkie warny naprawiać, a na pewno w końcowych wersjach kodu czy też przed opublikowaniem.



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

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

roske napisał(a):
Przecież napisałem że wywali błąd, co jeszcze miałem sprawdzić?

no właśnie co tu jeszcze sprawdzać skoro wywali błąd

A sprawdzałeś z TRZEMA plikami ?

Potrafisz wyjaśnić to o czym pisałeś i co pokazywałeś bez zadawania zagadek ? forumowiczom ? ... ja wiem co masz na myśli albo się domyślam i chętnie poznałbym twoje wyjaśnienia - a później moglibyśmy to skonfrontować z moimi

wtedy byłby pożytek z dyskusji dla innych

natomiast ty wolisz robić kalambury - ja również uważam że warto przećwiczyć wszystko o czym była mowa i spróbować to zrobić samemu - mając wyświetlacz LCD albo RS232 pod ręką da radę to zrobić na AVR GCC ;)

można się dużo nauczyć i zobaczyć, że jeśli się pisze kod niezgodnie z zasadami C to pojawia się BŁĄD ;) tymczasem gdy zrozumiemy jak działa C i piszemy kod zgodnie z jego zasadami to nie będzie błędu i będziemy mieli zmienne globalne i będziemy wiedzieli co i jak działa ...

------------------------ [ Dodano po: 3 minutach ]

Zealota napisał(a):
Pewnie ten void to szczegół, ale chyba dobre praktyki programowania "zalecają" by o tym pamiętać.


dokładnie jak piszesz - to nie jest błąd i wielu programistów nie wpisuje tego void. Ja wpisuję dla lepszej przejrzystości kodu - lepiej widać na pierwszy rzut oka że to funkcja bez argumentów ... chociaż wiem, że inni mogą się przyczepić że ja się czepiam ;) .... nie nie - każdy będzie pisał jak sobie chce. Gdy zaś pójdzie do pracy i będzie miał pracować w zespole to już nie będzie tak różowo - bo będzie trzeba przyjąć zasady zespołu a jeśli będą one właśnie takie konserwatywne to pewnie będzie trudno się odzwyczaić i co chwilę będzie się dostawać po uszach od kolegów ;)

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

Zealota napisał(a):
Ja u siebie staram się wszystkie warny naprawiać, a na pewno w końcowych wersjach kodu czy też przed opublikowaniem.

ja tak samo - ale już nawet nie pisałem o tym warnie chociaż widać na pierwszy rzut oka że wyskoczy bo nie ma deklaracji funkcji w pliku H .... Ale uznałem to już za swego typu literówkę, żeby nie odchodzić od meritum sprawy - bo jak mówiłem to co kolega odstawia w plikach H woła o pomstę do nieba ;) Mówię tu o umieszczaniu DEFINICJI zmiennej w H - i niech spróbuje ten plik zainkludować do kilku innych plików źródłowych w projekcie - będzie wielki armagedon i kicha ;)

Nie wspomnę już, że kolega kisiel no musi poduczyć się i zrozumieć różnice pomiędzy DEFINICJĄ a DEKLARACJĄ zmiennej

programując na prockach dość szybko da się to zauważyć i zrozumieć - zaś programując na PC ludzie często długo długo nie zdają sobie z tego sprawy - a błędy kompilacji łatają dziwnymi sposobami czasem na oślep

_________________
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 12:26 
Offline
Nowy

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

mirekk36 napisał(a):
Co widać zresztą po wypowiedziach, jakbyś połknął wszystkie rozumy świata - to ja ci tylko podpowiem, że ja jestem początkujący w języku C - to tak żebyśmy się rozumieli ok? Ja pisząc, dyskutując też się uczę .... ale jeszcze raz powtórzę - to co napisałeś


Nawet tego nie skomentuje, wycieczki osobiste nie są tutaj meritum problemu.

mirekk36 napisał(a):
to jest wierutna BZDURA niestety. Ba, to co napisałeś pokazuje nawet, że ty chyba nie wiesz (tak się domyślam tylko), że np zmienne globalne są automatycznie inicjalizowane wartością = 0, więc gdybyś o tym wiedział to nie pisałbyś bzdur, że z definicją mamy do czynienia tylko wtedy gdy przypisujemy do niej jakąś wartość .... BZDURA NAD BZDURY!


No tak, bo wtedy to LINKER robi definicję a nie programista. Programista jedynie zadeklarował to że będzie zmienna typu danego i o danej nazwie. Z racji że jest to zmienna globalna, ona ma domyślną wartość 0, którą wpisuje linker. Dopiero jak wpiszę tam wartość to ja definiuje tam daną wartość.

mirekk36 napisał(a):
to raczej dla potwierdzenia że niestety kompletnie nie rozumiesz o co chodzi, już wyjaśniam - to co zrobiłeś ;) ten program który napisałeś rzekomo dla potwierdzenia - po wstępnej fazie kompilacji przez PREPROCESOR o czym też zdajesz się nie wiedzieć będzie wyglądał TAK (zdziwisz się pewnie teraz)


W tym przykładzie masz racje, przeniesie zmienną "zmienna" do pliku .c ale w pliku .h nie ma ani deklaracji ani definicji zmiennej "zmienna_extern" a mimo to ona zmienia swoją wartość po uruchomieniu funkcji init();


Poprawiona wersja programu, żeby rozwiać wszelkie wątpliwości:

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.


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.


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.


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


Jak widać nie ma tutaj extern, jak i nie ma definicji/deklaracji zmiennej w pliku nagłówkowym, a jednak magicznie ona zmienia swoją wartość, a więc jest ona zmienną globalną w obrębie całej jednostki kompilacji.

Co do sporu deklaracja/definicja. Wynik kompilacji mówi jedno, w momencie kiedy mamy wiele "deklaracji"
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

w kodzie, kompilator to łyknie bez żadnego problemu, jednak jeżeli już w 2 miejscach damy
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

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


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


Zealota napisał(a):
No chyba jednak Kolega kisiel nie sprawdza tego co pisze.


Sprawdzam i kompiluje, ale przy kopiowaniu musiałem przez niedopatrzenie wyciąć za dużo. Mój błąd i dziękuje za zwrócenie uwagi, kody poprawiłem :)

Zealota napisał(a):
A może w tzw "zawodowym programowaniu" to już się nie patrzy na takie drobiazgi?

Patrzy się jeszcze surowiej, ale tutaj to miał być tylko przykład, a ta część nic nie wnosiła merytorycznie i nic nie zmieniała.

Zealota napisał(a):
Ja u siebie staram się wszystkie warny naprawiać, a na pewno w końcowych wersjach kodu czy też przed opublikowaniem.

Bardzo dobry nawyk i jak i również wymóg przed każdym wypuszczeniem nowej wersji oprogramowania :)

Dlaczego brak odniesienia co do dokumentacji, którą przytoczyłem?

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

mirekk36 napisał(a):
ja tak samo - ale już nawet nie pisałem o tym warnie chociaż widać na pierwszy rzut oka że wyskoczy bo nie ma deklaracji funkcji w pliku H .... Ale uznałem to już za swego typu literówkę, żeby nie odchodzić od meritum sprawy - bo jak mówiłem to co kolega odstawia w plikach H woła o pomstę do nieba ;) Mówię tu o umieszczaniu DEFINICJI zmiennej w H - i niech spróbuje ten plik zainkludować do kilku innych plików źródłowych w projekcie - będzie wielki armagedon i kicha ;)


no to tak:

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


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


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.


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.


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.


Na wycieczki osobiste nie odpowiadam, wiem co to deklaracja i co to definicja i dlaczego i jak to jest nazywane. 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. Wspomniałem o tym, jak przytoczyłem dokumentacje. Brak odniesienia do niej traktuje jako przytaknięcie temu co zostało napisane a więc również temu co pisałem ja i parę innych osób powyżej. Życzę miłej zabawy i kiszenia się w we własnym sosie.

Pozdrawiam



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

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

... wróć jeszcze raz bo chyba edytowałeś post jak odpisywałem

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

chłopie twój plik module.h to BZDURA


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.


ponieważ robisz DEFINICJĘ zmiennej w pliku nagłówkowym

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

oczywiście sekcja pliku H

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


spowoduje, że nie będzie multiple definition zmienna - ale jak wspominałem DEFINICJI nie robimy w plikach nagłówkowych. Teraz już widzę dlaczego nie rozumiesz specyfikatora "extern" i dlaczego on dla ciebie może nie istnieć

------------------------ [ Dodano po: 24 minutach ]

Co więcej - takie podejście WCALE nie oznacza, że zmienne są GLOBALNE tak jak próbowałeś się podłączyć do wypowiedzi roske - bo on przynajmniej takiego BABOLA nie robił

Posłuchaj więc prostej zasady ale przez chwilę na spokojnie i ze zrozumieniem:

Masz np jakiś plik źródłowy keyboard.c w którym oprogramowujesz sobie obsługę klawiatury - sama nazwa już podpowiada. Masz stworzony do niego plik nagłówkowy keyboard.h dzięki któremu możesz przekazywać do innych plików projektu nagłówki funkcji ...

Ale w takim pliku załóżmy że musisz mieć jakąś zmienną GLOBALNĄ key_status, która ma być dostępna dla KAŻDEGO innego pliku projektu, który zechce skorzystać czy to z tej zmiennej czy to z funkcji z pliku *.c wtedy zgodnie z zasadą języka C piszesz to TAK (zobacz to nie jest trudne)

keyboard.c

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


wtedy tworzymy plik:

keyboard.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 w tej sytuacji WSZYSTKO jest klarowne i nie ma zagrożeń. Pewnie zapytasz jakie zagrożenia mogą być w przypadku twojego pomieszania i używania definicji w plikach nagłówkowych? No to proszę mogę podać ci jeden przykład - i może do ciebie dotrze dlaczego WARTO trzymać się PODSTAWOWYCH zasad C .... przeczytaj dalej uważnie.

Załóżmy że mamy jednak w pliku keyboard.h po twojemu - czyli bzdurę:

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


jakie są zagrożenia ? - wyobraź sobie, że na pewnym etapie rozwoju projektu w którym już masz jakieś 50 plików źródłowych i używałeś zmiennej key_status powiedzmy w około 30 z nich.

I teraz przychodzi inna koncepcja wg której wyłączamy z kompilacji plik (UWAŻAJ) keyboard.c bo jest nam niepotrzebny. Po to bo np chcemy przetestować jakieś wycieki pamięci, albo w ogóle zajętość stosu bo czujemy że są problemy - więc staramy się pozbyć (wykluczyć) plik źródłowy z kompilacji - NIE USUWAMY go tylko wyłączamy z kompilacji .... I CO TERAZ PANIE KOCHANY ?

KICHA na MAXA .... ponieważ - ja spodziewam się, że po wyłączeniu takiego pliku źródłowego kompilator zwolni mi miejsce w pamięci RAM po zmiennych globalnych, które były używane w nim

tymczasem w związku z tym, że odstawiamy KICHĘ i tworzymy DEFINICJĘ zmiennej w pliku H który był zainkludowany w wielu innych plikach projektu, gdzie w części z nich korzystaliśmy np TYLKO ze zmiennej key_state i funkcji w nim zawartych (To tu się szybko dowiemy) bo kompilator zwymiotuje błędami, że nie widzi funkcji prawda ?

ale co się stanie z tymi plikami C które miały zainkludowany keyboard.h czyli są w nim wciąż nagłówki funkcji: fun1, fun2, fun3 z których ten plik nie korzysta ale KORZYSTA ze zmiennej key-state !!!!!!

ROZUMIESZ BYKA JAKIEGO ROBISZ ?

nie dość, że przez to podejście wciąż pozostają zajęte DWA bajty RAM, to jeszcze inne moduły mogą w ogóle błędnie działać ponieważ będą wciąż oczekiwać na jakieś wartości ze zmiennej key_state , która w tym wypadku ZAWSZE będzie miała wartość 0xFF bo tak ją zainicjalizowałeś i nigdy się nie zmieni bo jak ? skoro miziana była tylko przez funkcje z pliku keyboard.c

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

WYSTARCZY zastosować prawidłowe podejście o jakim piszę i z TAKIMI problemami NIGDY się nie spotkasz .... Będziesz wprawdzie ZMUSZONY poprawić wiele miejsc w projekcie w plikach które korzystały z key_state ponieważ przy ona ZNIKNIE przy prawidłowym podejściu ! ale za to nie będziesz wyrywał włosów z głowy dlaczego coś ci tam nie działa.

QURDĘ to takie proste w zastosowaniu a ty się kłócisz o to, że jak ci kompilator "łyka" albo "tobie" działa to oznacza, że to jest w porządku ?

_________________
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  
 
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ę 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 0 gości


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