Co zwróci funkcja?

Odpowiedz Nowy wątek
2019-02-11 00:51
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?

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: furious programming, 2019-02-11 03:27

Pozostało 580 znaków

2019-02-11 01:11
0

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

Przepraszam, usunąłem posta, nie wiedziałem, że widziałeś. Dla ciekawskich, w poprzednim poście napisałem, że main zwróci 0. - stryku 2019-02-11 01:12

Pozostało 580 znaków

2019-02-11 01:11
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, 2019-02-11 01:12
Undefined behaviour - stryku 2019-02-11 01:12

Pozostało 580 znaków

2019-02-11 08:10
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.

Pozostało 580 znaków

2019-02-11 08:34
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):

#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, 2019-02-11 08:57
Kluczowe jest tu stwierdzenie Na mojej maszynie. - vpiotr 2019-02-11 08:59
Nie znam maszyny PC gdzie przekręcanie zakresu int by miało powodować UB. - MasterBLB 2019-02-11 09:30
@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. - hauleth 2019-02-11 11:23

Pozostało 580 znaków

2019-02-11 09:27
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, 2019-02-11 09:32
2019-02-11 10:34
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, 2019-02-11 10:34

Pozostało 580 znaków

2019-02-11 11:26
0

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

#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 ;)

edytowany 1x, ostatnio: tajny_agent, 2019-02-11 11:26
Na moje oko Bracie to się nie skompiluje :P Ale tak bez żartów to domyślam się, o co Ci chodzi. - MasterBLB 2019-02-11 12:29
Trzeba tylko wyprowadzić value z Unii Europejskiej, czyli zamiast value zrobić val :P - tajny_agent 2019-02-11 14:29

Pozostało 580 znaków

2019-02-11 11:57
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.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0