Co zwróci funkcja?

Co zwróci funkcja?
M1
  • Rejestracja:ponad 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:14
0

Zakłada się, że zmienne typu int zajmują dwa bajty i są pamiętane w kodzie U2. Zakłada się ponadto, że
komputer, na którym implementowany jest poniższy program nie sygnalizuje błędów spowodowanych
przekroczeniem zakresu wartości zmiennych. Jak zakończy się działanie poniższego programu?

Kopiuj
int main () {
 const int maxint = 32767;
 int a = maxint-4;
 int b = 5;
 while (a<maxint) {
 a--;
 b++;
 }
 cout << b;
}

A drugie pytanie mam takie: co zwróci funkjca abs() dla najbardziej ujemnej liczby?

edytowany 1x, ostatnio: flowCRANE
M1
  • Rejestracja:ponad 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:14
0

Chodziło może bardziej co wypisze (jakie b)

stryku
Przepraszam, usunąłem posta, nie wiedziałem, że widziałeś. Dla ciekawskich, w poprzednim poście napisałem, że main zwróci 0.
stryku
  • Rejestracja:ponad 11 lat
  • Ostatnio:prawie 2 lata
  • Postów:607
0

Jak na moje masz UB. Nie ważne, że 'komputer nie sygnalizuje błędów', kompilator może przy cout << b wypisać choinkę.

edytowany 1x, ostatnio: stryku
stryku
Undefined behaviour
Maria Ulitzka
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 2 lata
  • Postów:11
5

Mamy UB tutaj. Czytamy:

When signed integer arithmetic operation overflows (the result does not fit in the result type), the behavior is undefined: it may wrap around according to the rules of the representation (typically 2's complement), it may trap on some platforms or due to compiler options (e.g. -ftrapv in GCC and Clang), or may be completely optimized out by the compiler.

MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:8 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

Żadne tam UB, po prostu nastąpi przekręcenie zakresu a i b. Na mojej maszynie, gdzie wielkość a i b to 4 bajty, dla b pokazał -2147450879.
A tu przykład jak to działa (wymaga C++14):

Kopiuj
#include <iostream>

int main()
{
    std::cout << "Przykład przekręcania licznika -1 (zapis binarny 8x1111B) do 0\n";
    int a = 0b1111'1111'1111'1111'1111'1111'1111'1111;
    std::cout << "a =" << a << ", a + 1 = " << a + 1 <<"\n";
    
    std::cout << "Przykład przekręcania licznika z liczby ujemnej do dodaniej (zapis binarny 1(0)B)\n";
    int b = 0b1000'0000'0000'0000'0000'0000'0000'0000;
    std::cout << "b =" << b << ", b - 1 = " << b - 1;

    return 0;
}

https://onlinegdb.com/SkMkjjRVE


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
edytowany 4x, ostatnio: MasterBLB
vpiotr
Kluczowe jest tu stwierdzenie Na mojej maszynie.
MasterBLB
Nie znam maszyny PC gdzie przekręcanie zakresu int by miało powodować UB.
hauleth
@MasterBLB: na każdej, w C++ signed overflow is UB i może spowodować, że jakiś kod zostanie wyoptymalizowany, przykładowo if (a < a + 1) puts("Yo!"); w przypadku gdy a jest signed intem zostanie zamienione na samo puts("Yo!"); bo kompilator może założyć, że a < a + 1 jest zawsze prawdziwe.
AP
  • Rejestracja:około 6 lat
  • Ostatnio:około 6 lat
  • Postów:6
2

Największa i najmniejsza możliwa wartość typu int w systemach 64-bitowych to + 2 147 483 647 oraz - 2 147 483 648 (wielkości stałych symbolicznych preprocesora znajdziesz w pliku <climits>).
Program w kolejnych pętlach zmniejsza a i zwiększa b . Zmienne **a ** i **b ** będą zachowywały się jak licznik kilometrów. Z chwilą przekroczenia wartości -2 147 483 648 a będzie zaczynała zmniejszanie od 2 147 483 647. Po przekroczeniu + 2 147 483 647 b będzie się zwiększało od - 2 147 483 648. Jak obliczyć b na koniec działania programu? Obliczasz ilośc razy jaką trzeba zmniejszyć a, aby spełniony był warunek wyjścia z pętli, czyli =32763-(-2147483648)=2 147 516 411 razy. Ponieważ b brakuje do "przekręcenia licznika: 2147483647-5=2 147 483 642 zwiększeń, obliczamy 2 147 516 411 - 2 147 483 642 = 32 769, A następnie zliczamy ile razy b zwiększy się już po przękręceniu licznika - 2 147 483 648+32 769=-2 147 450 879. Odpowiedź: b zatrzyma się na wartości -2 147 450 879, abs(b)=2 147 450 879

Dość upierdliwe to zadanie. Nauczyciel sadysta. Szkoda czasu na naukę czegoś takiego. Życie płynie.

edytowany 5x, ostatnio: Apurimac
AP
  • Rejestracja:około 6 lat
  • Ostatnio:około 6 lat
  • Postów:6
0
maciox123 napisał(a):

A drugie pytanie mam takie: co zwróci funkjca abs() dla najbardziej ujemnej liczby?

Mały niuansik, o którym nie należy zapominać. Najmniejszą wartością jaka przyjmie b w trakcie wykonywania kodu będzie: -2147483648, czyli abs(min{b})=2 147 483 648

edytowany 2x, ostatnio: Apurimac
tajny_agent
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad rok
  • Postów:1340
0

@MasterBLB: Mimo wszystko można się łatwo naciąć przy przekręcaniu signed.

Kopiuj
#include <iostream>
#include <limits>

int main(int, char**)
{
  int value = std::numeric_limits<int>::max();
  std::cout << val + 1 << " > " << val << " ? => " << std::boolalpha << (val + 1 > val) << "\n";
  return 0;
}

Bez optymalizacji dostaniesz false, z optymalizacją dostaniesz true ;)


"I love C++. It's the best language in the world right now for me to write the code that i need and want to write"
~ Herb Sutter
edytowany 1x, ostatnio: tajny_agent
MasterBLB
Na moje oko Bracie to się nie skompiluje :P Ale tak bez żartów to domyślam się, o co Ci chodzi.
tajny_agent
Trzeba tylko wyprowadzić value z Unii Europejskiej, czyli zamiast value zrobić val :P
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:2 minuty
2

Żeby było jasne Undefined Behavior w C++ oznacza, że standard nie nakłada żadnych więzów na implementację jaką ma wykonać kompilator.
Celem Undefined Behavior w standardzie C i C++, jest danie takiej wolności implementacji kompilatora, by kod działał szybko na każdej możliwej maszynie.
Jeśli jest jakaś dziwna platforma, to kompilator nie powinien być zmuszony do emulowania zachowania popularnych platform.

Przepełnienie dla unsigned int jest niezdefiniowane w standardzie, bo po prostu nie wszystkie platformy używają U2 (takich maszyn które nie stosują U2 jest niewiele, większość starsza niż 30 lat, ale istnieją i standard musi je uwzględniać).
Mało tego istnieją maszyny, które stosują w obliczaniach całkowitych system dziesiętny (cyfry dziesiętne zapisane są binarnie, ale obliczania są robione w systemie dziesiętnym).

Tak samo standard nie definiuje co się powinno stać jeśli wskaźnik pokazuje na zły obiekt.
Generalnie chodzi mi o to, że Undefined Behavior wcale nie musi oznaczać błędu albo crash-a.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)