2012-05-23 8 views
7

Mam następującą procedurę:Dlaczego kompilator pomija przypisując zmiennej

procedure GetDegree(const num : DWORD ; var degree : DWORD ; min ,sec : Extended); 
begin 
    degree := num div (500*60*60); 
    min := num div (500*60) - degree *60; 
    sec := num/500 - min *60 - degree *60*60; 
end; 

Po zmienny stopień zostanie przypisany przeskakuje debugera do końca postępowania. Dlaczego?

Odpowiedz

17

To jest optymalizacja. Zmienne min isą przekazywane przez wartość. Oznacza to, że zmiany nie są widoczne dla osoby dzwoniącej i są prywatne w stosunku do tej procedury. W związku z tym kompilator może stwierdzić, że przypisywanie im jest bezcelowe. Wartości przypisane do zmiennych nie mogą zostać odczytane. Dlatego kompilator decyduje się zaoszczędzić czas i pominąć zadania. Spodziewam się, że chodziło o stwierdzenie procedurę tak:

procedure GetDegree(const num: DWORD; var degree: DWORD; var min, sec: Extended); 

Jak powiedziałem w poprzednim pytaniu, nie ma naprawdę dużo punkt w użyciu Extended. Byłoby lepiej z jednym ze standardowych typów zmiennoprzecinkowych, Single lub Double. Lub nawet za pomocą generic Real, który mapuje do Double.

Ponadto zadeklarowano, że min jest typu zmiennoprzecinkowego, ale obliczenie oblicza liczbę całkowitą. Moja odpowiedź na poprzednie pytanie jest dość precyzyjna w tym względzie.


Polecam utworzenie rekordu do przechowywania tych wartości. Przekazywanie trzech oddzielnych zmiennych sprawia, że ​​twoje interfejsy funkcyjne są bardzo niechlujne i przerywają enkapsulację. Te trzy wartości mają znaczenie tylko wtedy, gdy są rozpatrywane jako całość.

type 
    TGlobalCoordinate = record 
    Degrees: Integer; 
    Minutes: Integer; 
    Seconds: Real; 
    end; 

function LongLatToGlobalCoordinate(const LongLat: DWORD): TGlobalCoordinate; 
begin 
    Result.Degrees := LongLat div (500*60*60); 
    Result.Minutes := LongLat div (500*60) - Result.Degrees*60; 
    Result.Seconds := LongLat/500 - Result.Minutes*60 - Result.Degrees*60*60; 
end; 

function GlobalCoordinateToLongLat(const Coord: TGlobalCoordinate): DWORD; 
begin 
    Result := Round(500*(Coord.Seconds + Coord.Minutes*60 + Coord.Degrees*60*60)); 
end; 
+0

Dzięki ponownie David zostałeś ogromną pomocą today.Didn't wiedział o tych cholernych optimzations mogę usunąć je z tego kawałka kodu? – opc0de

+6

@ opc0de Nie chcesz usuwać optymalizacji. Chcesz naprawić swój kod, aby zwracał wartości "min" i "sec" do osoby dzwoniącej. W przeciwnym razie, dlaczego zawracacie sobie głowę ich obliczaniem? –

+0

Ok, weź to teraz. Jeszcze raz dzięki głupiemu błędowi :)! – opc0de