ATNEL tech-forum
https://forum.atnel.pl/

PUŁAPKI UMYSŁU w języku C - część 02
https://forum.atnel.pl/topic22765.html
Strona 1 z 1

Autor:  mirekk36 [ 30 gru 2019, o 15:52 ]
Tytuł:  PUŁAPKI UMYSŁU w języku C - część 02

zapraszamy dzisiaj o 19:00 ;)

Obrazek

Autor:  lukasz_0xfff [ 30 gru 2019, o 20:01 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Obrazek
I mały komentarz do obrazka konwersja typów wskaźników nie należy do rzutowań nie jawnych. Taki stan rzeczy w zasadzie jest właśnie dobry. Ponieważ gdy zmieniamy typy wskaźników to musimy wiedzieć co robimy( dla tego dodajemy rzutowanie jawnie ) a nie zrobić tego przypadkiem przez pomyłkę co mogło by spowodować sporo błędów w programie i gdyby nie ostrzenie mógłby być problem z odnalezieniem błędu.

Autor:  Rosto [ 30 gru 2019, o 23:09 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Mówią, że jeden obrazek jest wart więcej niż 1000 słów, no to zrobiłem obrazek.

Czarne ramki oznaczają adresy w pamięci, które przechowują obydwa wskaźniki pod koniec programu i sposób w jaki dane są interpretowane. Mam nadzieję, że po takiej dawce łopatologii, komuś zaświeci się w głowie żarówka. W razie dodatkowych pytań, walcie śmiało.

Obrazek

Autor:  tomcat65 [ 31 gru 2019, o 00:53 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Fajna tabelka. Chociaż typowałem a=1, b=258, w zasadzie potwierdza mój tok rozumowania, czyli:
- podział wartości 16 bitowej na 2 x 8 bit i pobranie jednego bajta dla tab1
- "zsumowanie" dwóch 8 bitowych elementów tab2, a raczej połączenie w jedną 16bit.
I wszystko ok, gdyby nie jedna rzecz, której nie rozumiem - czemu to idzie " od tyłu" ?

Wrzuciłem to zadanie na Rpi, oczywiście dwa ostrzeżenia i brak kompilacji. Po poprawieniu typów wskaźników, czyli
uint16_t * wsk1 = tab1;
uint8_t * wsk2 = tab2;
poszło, wartości to: a=612, b=99.
Nie wiem, czy można w tym kompilatorze ( gcc ) wyłączyć warningi i kompilować mimo błędów.

Autor:  gizmo5418 [ 31 gru 2019, o 01:17 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

tomcat65 napisał(a):
Nie wiem, czy można w tym kompilatorze ( gcc ) wyłączyć warningi i kompilować mimo błędów.

Jak najbardziej można kompilować z warningami. Nic nie piszesz natomiast, w jaki sposób kompilujesz, jakich przełączników dla gcc używasz...

Autor:  tomcat65 [ 31 gru 2019, o 01:38 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

gizmo5418 napisał(a):
w jaki sposób kompilujesz, jakich przełączników dla gcc używasz...


Ponieważ "bawię się" tylko przez konsolę, jedyna znana mi opcja to 'gcc -o' .

Autor:  Rosto [ 31 gru 2019, o 02:03 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

tomcat65 napisał(a):
I wszystko ok, gdyby nie jedna rzecz, której nie rozumiem - czemu to idzie " od tyłu" ?

Wszystko rozbija się o to, w jaki sposób zapisują i czytają liczby ludzie, a w jaki mikrokontrolery przechowują je w pamięci.

AVR to architektura Little Endian, dlatego w przypadku danych składających się z kilku bajtów, LSB (Least Significant Byte) jest zapisywany pod niższym adresem, a MSB (Most Significant Byte) pod wyższym. Ludzie zapisują liczby od lewej do prawej, stąd zamieszanie. Na szczęście większość narzędzi programistycznych można skonfigurować, żeby wyświetlały dane w pamięci na obydwa sposoby.

Proponuję wyguglować materiały na temat Endianness.

----------------------------
Wrzucam nową wersję obrazka, z lekko zmienionym formatowaniem, które powinno poprawić czytelność.

Obrazek

Autor:  gizmo5418 [ 31 gru 2019, o 08:11 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Rosto napisał(a):
Wszystko rozbija się o to, w jaki sposób zapisują i czytają liczby ludzie, a w jaki mikrokontrolery przechowują je w pamięci.

AVR to architektura Little Endian, dlatego w przypadku danych składających się z kilku bajtów, LSB (Least Significant Byte) jest zapisywany pod niższym adresem, a MSB (Most Significant Byte) pod wyższym. Ludzie zapisują liczby od lewej do prawej, stąd zamieszanie. Na szczęście większość narzędzi programistycznych można skonfigurować, żeby wyświetlały dane w pamięci na obydwa sposoby.

Proponuję wyguglować materiały na temat Endianness.

Z tą kolejnością bajtów w pamięci w zależności od architektury się zgadza, ale....
Program, bez względu na jakiej platformie kompilowany, ma się wykonywać w taki sam sposób. O to dba kompilator. Z punktu widzenia programisty nie ma to znaczenia !!!

To, że u kolegi tomcat65 wychodzą inne wartości, spowodowane jest tym, że nie przepisał dokładnie programu, tylko....
Może sam się zorientuje co w jego przykładzie jest zamienione:
tomcat65 napisał(a):
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Jeżeli zostało to celowo zamienione ( aby np. kompilacja przebiegła do końca bez błędów ), to nie zrozumiałe jest zaskoczenie spowodowane innym wynikiem. Przecież ten zapis nie jest równoznaczny z tym, który przedstawiony jest w zadaniu.
Gdyby tomcat65 rzucił okiem na drugi post, w którym jest podane rozwiązanie występowania owych warningów przy kompilacji...

Autor:  tomcat65 [ 31 gru 2019, o 13:08 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Ok, ponimaju zapis, i fakt odcztu od MSB dla wartości > 8bit.

Kol. gizmo - jakiś problem z czytaniem ze zrozumieniem? :)
Niczemu się nie dziwię, przedstawiłem efekt działania.
Jak będę znał przełączniki dla kompilatora, aby pomijał błędy i ostrzeżenia - wtedy puszczę taką kompilację i zobaczę co wyjdzie. Wyniki przedstawię.

Poprawienie błędu było zresztą kolejnym zadaniem.

Autor:  mirekk36 [ 31 gru 2019, o 13:22 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

tomcat65 napisał(a):
Jak będę znał przełączniki dla kompilatora, aby pomijał błędy i ostrzeżenia

Nie trzeba znać takich przełączników a wręcz unikać ich włączania - tu chodzi (mała podpowiedź - o zastosowanie JAWNEGO rzutowania) ;)

Autor:  tomcat65 [ 31 gru 2019, o 13:35 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

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


Bez przełączników, rzutowanie jawne.
Wynik : a=2, b =513.

Dzięki panowie, za wyjaśnienia.
Nie bardzo wiem, jak wam tu pochwały złożyć :) .

Autor:  Rosto [ 31 gru 2019, o 16:04 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

tomcat65 napisał(a):
Dzięki panowie, za wyjaśnienia.
Nie bardzo wiem, jak wam tu pochwały złożyć :) .

Podaję numer konta...

A tak na serio:
Nikt nie rodzi się ze znajomością wskaźników. Kiedy zacząłem rozumieć jak to działa, poczułem się jakbym miał super-moce. Zawsze chętnie pomogę komuś innemu zdobyć te same super-moce, bo trzeba nam więcej programistów, którzy wiedzą co się dzieje "pod maską".

Gratulacje, jesteś w elitarnym klubie programistów - mutantów.

Autor:  tischtennis [ 31 gru 2019, o 18:18 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

lukasz_0xfff napisał(a):
Obrazek
I mały komentarz do obrazka konwersja typów wskaźników nie należy do rzutowań nie jawnych. Taki stan rzeczy w zasadzie jest właśnie dobry. Ponieważ gdy zmieniamy typy wskaźników to musimy wiedzieć co robimy( dla tego dodajemy rzutowanie jawnie ) a nie zrobić tego przypadkiem przez pomyłkę co mogło by spowodować sporo błędów w programie i gdyby nie ostrzenie mógłby być problem z odnalezieniem błędu.

coś dzwoni, ale nie w tym kościele :P

w C++ tak by się zachowało, w C - nie :P a wyraźnie mowa w temacie, że działamy w języku C

doczytaj sobie jakie są różnice w tym słowie kluczowym między C i Cpp

Autor:  tomcat65 [ 31 gru 2019, o 18:31 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Rosto napisał(a):
Gratulacje, jesteś w elitarnym klubie programistów - mutantów

Dziękuję, miło łechcą komplementy i pochlebstwa :) , zwłaszcza to o programiście - którym nigdy nie byłem i już nie będę. A jako żem ciekaw świata, trochę C liznąłem.

Wszystkim wszystkiego najlepszego w Nowym Roku.

P.S. Odnośnie zagadki - poza zrozumieniem działania wskaźników, czy do czegokolwiek taka sztuczka może być przydatna?

Autor:  mirekk36 [ 31 gru 2019, o 20:36 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Cytuj:
P.S. Odnośnie zagadki - poza zrozumieniem działania wskaźników, czy do czegokolwiek taka sztuczka może być przydatna?

To nie jest żadna sztuczka, w trakcie programowania czasem się zdarza wykorzystać takie właściwości - a z drugiej strony im lepiej się zrozumie działanie wskaźników tym więcej później przychodzi pomysłów na ich zastosowanie we własnych programach.

Autor:  Rosto [ 1 sty 2020, o 02:09 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Już po północy, więc zanim pójdę spać, wrzucam swoje uwagi na temat części trzeciej.

W czasie streamu ktoś twierdził, że funkcja get_data() nie może być zdefiniowana w main(), ale (co zademonstrował pan Mirek) GCC posiada rozszerzenie, które sobie z tym radzi.

Moim zdaniem problemem jest to, że zmienna `i` jest używana przez funkcję get_data() do przechowywania stanu PINC, a później ta sama zmienna służy jako licznik w pętli `for`. W konsekwencji, jeśli PINC będzie mieć wartość 199 lub większą, pętla zakończy się przedwcześnie.

Można to rozwiązać na kilka sposobów:
1. Stworzyć lokalną wersję zmiennej `i` w get_data():
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

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

3. Stworzyć osobną zmienną, która będzie używana tylko jako licznik pętli.
4. Zamiast
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

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

Autor:  mirekk36 [ 1 sty 2020, o 05:06 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Rosto napisał(a):
Już po północy, więc zanim pójdę spać, wrzucam swoje uwagi na temat części trzeciej.

No i kolega bezbłędnie i jako pierwszy rozwiązał psychodeliczną zagadkę ;) Gratulacje!

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

A takie funkcje nazywają się "Nested Functions" czyli "Funkcje zagnieżdżone" ;) I o dziwo - bo sam się kiedyś zdziwiłem AVR GCC śmiało je potrafi obsługiwać ;). Jedną z ich wad jest właśnie to że trzeba uważać na zmienne lokalne - ponieważ nieopatrznie można dokonać ich nadpisania tak jak wyjaśnił słusznie kolega wyżej ;)

Autor:  Alef2 [ 1 sty 2020, o 11:29 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

tomcat65 napisał(a):
poza zrozumieniem działania wskaźników, czy do czegokolwiek taka sztuczka może być przydatna?
dołączaam się do pytania
Moim zdaniem można to wykorzystać do "wyłuskiwqania" konkretnego bajtu z liczby wielobajtowej. A to można wykorzystać np. do szybkiego obliczania kwadratu (wyliczanie RMS), i wyższych potęg (aproksymacja szeregiem). Chętnie poznam inne zastosowania i Wasze opinie.
Rosto napisał(a):
Moim zdaniem problemem jest to, że zmienna `i` jest używana przez funkcję get_data()
Tu mam trochę odmienne zdanie, może dzielę włos na czworo lub nazwiecie mnie malkontentem, ale...
Nie zostało podane do czego ma dany kod służyć. Więc poszedłem z drugiej strony i zastanowiłem się, gdzie taki kod miałby zastosowanie. Wyobraźmy sobie maszynę, która może rozpocząć działanie dopiero w określonej pozycji, dopóki tej pozycji nie osiągnie ma nic nie robić. Dla PINC mniejszego od 199 pokazuje wartość PINC, dla większego idzie dalej i COŚ robi. W takim układzie pętli for nadanie wartości i inkrementacja są zbędne, ale nie przeszkadzają.
Jestem bardzo ciekaw Waszych opinii.

Autor:  lukasz_0xfff [ 1 sty 2020, o 14:33 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

tischtennis napisał(a):
lukasz_0xfff napisał(a):
Obrazek
I mały komentarz do obrazka konwersja typów wskaźników nie należy do rzutowań nie jawnych. Taki stan rzeczy w zasadzie jest właśnie dobry. Ponieważ gdy zmieniamy typy wskaźników to musimy wiedzieć co robimy( dla tego dodajemy rzutowanie jawnie ) a nie zrobić tego przypadkiem przez pomyłkę co mogło by spowodować sporo błędów w programie i gdyby nie ostrzenie mógłby być problem z odnalezieniem błędu.

coś dzwoni, ale nie w tym kościele :P

w C++ tak by się zachowało, w C - nie :P a wyraźnie mowa w temacie, że działamy w języku C

doczytaj sobie jakie są różnice w tym słowie kluczowym między C i Cpp

Otóż wszystko się zgadza, w C również zwróci wskaźnik adekwatny do typu tablicy nawet po worningu da się to wywnioskować, tak auto NIE istnieje w C ale w tym przypadku po prostu używając cpp można przez to pokazać jak myśli kompilator. Z resztą Cpp jest rozszerzeniem C tak więc w tych elementarnych rzeczach takich jak tablice i wskaźniki zachowa się tak samo.

Autor:  tischtennis [ 1 sty 2020, o 16:59 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Właśnie "auto" istnieje w C - mało tego jest domyślnie używane dla zmiennych lokalnych i dlatego nie trzeba tego pisać :P
Używając kompilatora Cpp zmieniasz całkiem znaczenie tego słowa kluczowego, więc nie pokazujesz wtedy "jak myśli kompilator" - bo to są 2 różne mechanizmy.
Zrób to samo ale bez auto w C - napisałeś, że to dzięki "auto" kompilator sam ogarnął typ - no nie. A to że nie podałeś typu spowodowało zadziałanie innego mechanizmu i tu auto nie ma nic do gadania w C.

Autor:  mirekk36 [ 2 sty 2020, o 00:08 ]
Tytuł:  Re: PUŁAPKI UMYSŁU w języku C - część 02

Alef2 napisał(a):
tomcat65 napisał(a):
poza zrozumieniem działania wskaźników, czy do czegokolwiek taka sztuczka może być przydatna?
dołączaam się do pytania
Moim zdaniem można to wykorzystać do "wyłuskiwqania" konkretnego bajtu z liczby wielobajtowej. A to można wykorzystać np. do szybkiego obliczania kwadratu (wyliczanie RMS), i wyższych potęg (aproksymacja szeregiem). Chętnie poznam inne zastosowania i Wasze opinie.
Rosto napisał(a):
Moim zdaniem problemem jest to, że zmienna `i` jest używana przez funkcję get_data()
Tu mam trochę odmienne zdanie, może dzielę włos na czworo lub nazwiecie mnie malkontentem, ale...
Nie zostało podane do czego ma dany kod służyć. Więc poszedłem z drugiej strony i zastanowiłem się, gdzie taki kod miałby zastosowanie. Wyobraźmy sobie maszynę, która może rozpocząć działanie dopiero w określonej pozycji, dopóki tej pozycji nie osiągnie ma nic nie robić. Dla PINC mniejszego od 199 pokazuje wartość PINC, dla większego idzie dalej i COŚ robi. W takim układzie pętli for nadanie wartości i inkrementacja są zbędne, ale nie przeszkadzają.
Jestem bardzo ciekaw Waszych opinii.


Uwierz mi sam kod nie ma żadnego znaczenia ;) ot wymyślone cokolwiek - a jedyny taki błąd jaki chciałem pokazać przy funkcjach zagnieżdżonych to właśnie problem z wykorzystaniem zmiennych lokalnych ;)

Strona 1 z 1 Strefa czasowa: UTC + 1
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/