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

Zmienna większa od uint8_t
https://forum.atnel.pl/topic21639.html
Strona 1 z 1

Autor:  zorro [ 30 lis 2018, o 19:53 ]
Tytuł:  Zmienna większa od uint8_t

Proszę o wyjaśnienie takiego zapisu:
Powołuję zmienną

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


Dlaczego to się kompiluje skoro powołana zmienna jest ośmio bitowa?
To jest kawałek programu.

Autor:  Zealota [ 30 lis 2018, o 20:07 ]
Tytuł:  Re: Zmienna większa od uint8_t

To jest właśnie siła języka C. Tu rządzi programista, ale niestety musi wiedzieć co robi, dlatego też zasady dotyczące wielkości zmiennych są bardzo elastyczne, a jedna z większej elastyczności to domyślna promocja do int.
Inaczej pisząc, to programista musi kontrolować zakres typów, a nie kompilator. Dzięki temu można robić "różne sztuczki" :)

Autor:  Daro69 [ 30 lis 2018, o 20:08 ]
Tytuł:  Re: Zmienna większa od uint8_t

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

powołujesz zmienną z wartością 0,
inkrementujesz do wartości 1,
oczekujesz na spełnienie 'ifa' który który nigdy się nie spełni, by ustawić wartość na PORTB.
poza ifem: zerujesz zmienną.

hmm. ale dlaczego nie krzyczy?
może dlatego że nie przypisujesz takiej wartości do zmiennej, a sprawdzać w ifie można cokolwiek :?
:)

Autor:  mirekk36 [ 30 lis 2018, o 21:47 ]
Tytuł:  Re: Zmienna większa od uint8_t

Daro69 napisał(a):
ja nie wiem dlaczego nie krzyczy.

A dlaczego miałby krzyczeć? Co szkodzi porównywać zawartość bajtu ze słowem ? Toż w zakresie 0-255 pokrywają się ich wartości ;) ... poza tym to co pisze wyżej kolega Zealota.

Autor:  Zealota [ 30 lis 2018, o 21:49 ]
Tytuł:  Re: Zmienna większa od uint8_t

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

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


oprócz tego tam jest niepotrzebny średnik.
Dodatkowo promocja do int jednak zapewni, że warunek się spełni.
Można rzutować na int8_t i wtedy już nie będzie działać.
Tak z praktyki dopiero ostatnio widzę, co było dla mnie długo mgliste, ten wszędobylski int :)
Nie potrafię już na to patrzeć, że co chwilę trzeba rzutować, żeby nie przekroczyć zakresu int dla dużych liczb, a to powoduje farfocle, oczopląsy i długaśne linijki :)
Przy AVR to zwykle, żaden problem, bo tam rządzi uint8_t, ale przy tych stm,ach to już trzeba się strzec :)

Autor:  zorro [ 1 gru 2018, o 08:35 ]
Tytuł:  Re: Zmienna większa od uint8_t

Zealota napisał(a):
To jest właśnie siła języka C. Tu rządzi programista, ale niestety musi wiedzieć co robi, dlatego też zasady dotyczące wielkości zmiennych są bardzo elastyczne, a jedna z większej elastyczności to domyślna promocja do int.
Inaczej pisząc, to programista musi kontrolować zakres typów, a nie kompilator. Dzięki temu można robić "różne sztuczki" :)

Nie rozumiem dlaczego promocja do int, skoro powołana zmienna jest określona uint8_t

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

Daro69 napisał(a):
hmm...
ja nie wiem dlaczego nie krzyczy.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

powołujesz zmienną z wartością 0,
inkrementujesz do wartości 1,
oczekujesz na spełnienie 'ifa' który który nigdy się nie spełni, by ustawić wartość na PORTB.
poza ifem: zerujesz zmienną.

hmm. ale dlaczego nie krzyczy?
może dlatego że nie przypisujesz takiej wartości do zmiennej, a sprawdzać w ifie można cokolwiek :?
:)

A gdzie inkremenuję do wartości 1?

Autor:  Piotrek_P [ 1 gru 2018, o 09:30 ]
Tytuł:  Re: Zmienna większa od uint8_t

W drugiej linii Twojego kodu, nie widzisz tego?;-)

Autor:  zorro [ 1 gru 2018, o 10:54 ]
Tytuł:  Re: Zmienna większa od uint8_t

Piotrek_P napisał(a):
W drugiej linii Twojego kodu, nie widzisz tego?;-)

Tak w drugiej linii inkrementuję zmienną, ale nie do jednego a do 500.

Autor:  skalarro [ 1 gru 2018, o 11:27 ]
Tytuł:  Re: Zmienna większa od uint8_t

zorro napisał(a):
uint8_t zmienna = 0;  //w przerwaniu wpisuję
zmienna++;
   if ( zmienna == 500 );
 
     PORTB = LED_TOG;
     zmienna = 0;


jak dla mnie nie zachodzi tu żadna promocja do int tylko zmienna jedzie sobie do 255 i się przepełnia i nigdy nie osiąga 500. Nikt nie zabroni sprawdzać czy jest równa nawet 10000000 bo dlaczego by nie. Po prostu zawsze będzie fałszywy warunek i już.
Poza tym warunek if ( zmienna == 500 ); jest pusty a reszta jest poza warunkiem, czyli port się togluje cały czas a zmienna zeruje się zawsze po 1.

Lepiej byłoby tak, choć wg mnie i tak się nie wykona warunek
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Cytuj:
A gdzie inkremenuję do wartości 1?

w każdym obiegu pętli. Na początku masz zmienna=0, potem zmienna++ czyli inkrementujesz do 1, potem pusty if, który i tak nigdy się nie wykona, następnie ZA KAŻDYM OBIEGIEM resetujesz zmienna.
 

Autor:  Zealota [ 1 gru 2018, o 11:39 ]
Tytuł:  Re: Zmienna większa od uint8_t

skalarro napisał(a):
jak dla mnie nie zachodzi tu żadna promocja do int tylko zmienna jedzie sobie do 255
 


Proponuję najpierw sprawdzić, kompilując kod.
Ja oczywiście sprawdziłem pod kompilatorem i dlatego jestem mądrzejszy.
To najlepsza forma nauki.

Autor:  skalarro [ 1 gru 2018, o 11:48 ]
Tytuł:  Re: Zmienna większa od uint8_t

Zealota napisał(a):
Ja oczywiście sprawdziłem pod kompilatorem i dlatego jestem mądrzejszy.

No to muszę doczytać... DO tej pory żyłem w przekonaniu, że dotyczy to działań typu dodawanie i mnożenie dwóch zmiennych a nie zwykłego inkrementowania. ALe w sumie jakby się tak zastanowić to zmienna++ to też dodawanie dwóch liczb.
Nie zmienia to faktu, że w tym wypadku if się i tak nie wykona bo zmienna nie dojdzie nigdy nawet do 2, a warunek jest pusty

Autor:  andrews [ 1 gru 2018, o 11:55 ]
Tytuł:  Re: Zmienna większa od uint8_t

Proponuję poczytać np. to (dość przystępny opis):
https://opensourceforu.com/2016/06/quic ... omotion-c/

Ewentualnie wpisać w Google "c promotion rules" i pojawi się sporo artykułów na ten temat.

Autor:  Zealota [ 1 gru 2018, o 12:48 ]
Tytuł:  Re: Zmienna większa od uint8_t

skalarro napisał(a):
Zealota napisał(a):
Ja oczywiście sprawdziłem pod kompilatorem i dlatego jestem mądrzejszy.

No to muszę doczytać... DO tej pory żyłem w przekonaniu, że dotyczy to działań typu dodawanie i mnożenie dwóch zmiennych a nie zwykłego inkrementowania. ALe w sumie jakby się tak zastanowić to zmienna++ to też dodawanie dwóch liczb.
Nie zmienia to faktu, że w tym wypadku if się i tak nie wykona bo zmienna nie dojdzie nigdy nawet do 2, a warunek jest pusty


Jeszcze hola hola.
Być może wczoraj trochę jednak niepotrzebnie zamieszałem, przepraszam :(
Zrobiłem kolejne testy i na razie mojej tezy o tym, że dojdzie do warunku zmienna == 500, z powodu promocji do int, nie mogę wykazać niestety, pomimo pracy z kompilacją.
Zgodnie z sugestią Kolegi andrews również mnie się należy dokształcenie...

Autor:  zorro [ 1 gru 2018, o 18:43 ]
Tytuł:  Re: Zmienna większa od uint8_t

skalarro napisał(a):
zorro napisał(a):
uint8_t zmienna = 0;  //w przerwaniu wpisuję
zmienna++;
   if ( zmienna == 500 );
 
     PORTB = LED_TOG;
     zmienna = 0;


jak dla mnie nie zachodzi tu żadna promocja do int tylko zmienna jedzie sobie do 255 i się przepełnia i nigdy nie osiąga 500. Nikt nie zabroni sprawdzać czy jest równa nawet 10000000 bo dlaczego by nie. Po prostu zawsze będzie fałszywy warunek i już.
Poza tym warunek if ( zmienna == 500 ); jest pusty a reszta jest poza warunkiem, czyli port się togluje cały czas a zmienna zeruje się zawsze po 1.

Lepiej byłoby tak, choć wg mnie i tak się nie wykona warunek
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Cytuj:
A gdzie inkremenuję do wartości 1?

w każdym obiegu pętli. Na początku masz zmienna=0, potem zmienna++ czyli inkrementujesz do 1, potem pusty if, który i tak nigdy się nie wykona, następnie ZA KAŻDYM OBIEGIEM resetujesz zmienna.
 


Inkrementacja zmiennej jest umieszczona w przerwaniu, więc w każdym przerwaniu wzrasta o wartość jeden.
Skąd się wzięło u was inkrementacja do 1.
Zmienna zerowana jest po warunku if nie po każdym obiegu. Tak ja to widzę.

Chodził mi oto, że powołałem zmienną ośmio bitową a w przerwaniu w warunku if wpisałem wartość 500 i kompilator
nie wyświetlił mi błędu a skompilował. Ja myślałem, iż największą wartość jaką można wpisać to 255,
Jeden z kolegów wyjaśnił, iż to programista ma pilnować wartości wpisywanych do warunku if.
To co podałem w pierwszym poście to tylko wybrany fragment kodu.

Dzięki wszystkim za wypowiedzi.

Autor:  skalarro [ 1 gru 2018, o 18:55 ]
Tytuł:  Re: Zmienna większa od uint8_t

zorro napisał(a):
Skąd się wzięło u was inkrementacja do 1.


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


Przeanalizuj co robi Twój warunek...

Albo zapisz go inaczej - będziesz widział co się dzieje"

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


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


Widzisz teraz skąd ta jedynka a nie 255 czy 500?

Autor:  Zealota [ 1 gru 2018, o 19:03 ]
Tytuł:  Re: Zmienna większa od uint8_t

zorro napisał(a):
Chodził mi oto, że powołałem zmienną ośmio bitową a w przerwaniu w warunku if wpisałem wartość 500 i kompilator
nie wyświetlił mi błędu a skompilował. Ja myślałem, iż największą wartość jaką można wpisać to 255

Wygląda na to, że w porównaniu kompilator nie sprawdza typu.

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


To dostaniemy ostrzeżenie. Porównanie to oczywiście nie to samo co przypisanie wartości do zmiennej.

Autor:  skalarro [ 1 gru 2018, o 19:16 ]
Tytuł:  Re: Zmienna większa od uint8_t

Zealota napisał(a):
Porównanie to oczywiście nie to samo co przypisanie wartości do zmiennej

Dokładnie. I to jest chyba podsumowanie tematu.
Bo kto programiście zabroni porównania np tak abstrakcyjnego i pozbawionego sensu jak if (zmienna== "elephant"){};

Można sprawdzić czy kolor_samochodu == kombi ;p
Oczywiście nie ma to sensu, typy niezgodne i nie mają prawa nigdy się zgodzić ale kompilator grzecznie to zaakceptuje a program ochoczo będzie sprawdzał warunek za każdym obiegiem... hehe

Autor:  andrews [ 1 gru 2018, o 20:38 ]
Tytuł:  Re: Zmienna większa od uint8_t

Zawsze można dodać do linii poleceń kompilatora opcję -Wtype-limits, która powinna w takim przypadku spowodować wyświetlenie ostrzeżenia w stylu:
"comparison is always false due to limited range of data type". Opcja ta jest też zawarta w zestawie opcji -Wextra.

EDIT:
Jeszcze tylko małe sprostowanie:
skalarro napisał(a):
a program ochoczo będzie sprawdzał warunek za każdym obiegiem

W tym przypadku nie będzie. Kod dokonujący porównania zostanie zoptymalizowany nawet przy wyłączonej optymalizacji. Tak samo nie zostanie w ogóle wygenerowany kod instrukcji wykonywanych w przypadku spełnienia warunku. Kompilator po prostu uzna, że sprawdzenie warunku zawsze zwróci fałsz.

Warunek będzie za to sprawdzany mimo bezsensownego porównania w przypadku porównania dwóch zmiennych o różnych typach, przykładowo:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Nastąpi tutaj promocja zmiennej zmienna do int, więc porównywane będą wartości 16-bitowe. W tej sytuacji wiadomo, że nie istnieje taka wartość zmiennej zmienna_int dla której porównanie mogłoby zwrócić prawdę (chyba, że wynik dodawania przekroczy zakres zmiennej 16-bitowej bez znaku), jednak w tym przypadku sprawdzanie warunku będzie się odbywać za każdym razem (praktycznie za każdym razem zwracając fałsz) i w dodatku żadne ostrzeżenie nie zostanie wygenerowane.

Innymi słowami i tak trzeba się pilnować ;)

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