2012-09-23 13 views
5

Przeszukałem i refaktoryzowałem kod. Skończyło się na zmianę funkcji z:Niedokładna i bliska niezgodność.

void setPerspective(float nearP = 0.1f, float farP = 1000.0f); 

do

void setPerspective(float near = 0.1f, float far = 1000.0f); 

i zaczęła się dużo dziwnych 'missing ;' i 'missing)' błędów.

Wygląda na to, że near i far#define d w windef.h. Słusznie; Uniknę ich użycia.

Ale potem zauważyłem w innym pliku nagłówka:

void setPerspective(float fov, float aspect, float near, float far); 

Jeszcze mam żadnych problemów. Oba te pliki nagłówkowe mają ten sam #include s ...

Każdy pomysł, dlaczego dostaję problemy w jednym, ale nie innym? Nie wydaje się być domyślnymi parametrami. Czy to jakieś arbitralne porządkowanie numerów #include, które mogą powodować problemy z jednym plikiem nagłówkowym, a nie innym?

+0

A może nagłówek albo nie definiuje "blisko" i "daleko" w zależności od pewnych warunków. –

Odpowiedz

7

Znaczniki near i far prawdopodobnie określa się pusta w pustym #define jak to

#define near 
#define far 

tak wstępnie procesor zastąpić je null - znikają przed kompilator przetwarzania źródła.

Pierwsza funkcja obejmuje zgłoszenie przyporządkowania domyślnego do parametrów

void setPerspective(float nearP = 0.1f, float farP = 1000.0f); 

Kompilator prawidłowo interpretuje nearP i farP nazwy parametru i float jako typu. Po zmianie nearP do near i farP do far pre-processor zastępuje je za nieważne i masz zadanie do rodzaju float ... i kompilator generuje dopasowanie ... to co kompilator widzi:

void setPerspective(float = 0.1f, float = 1000.0f); 

W drugim nagłówku pliku parametrów w prototypie funkcji nie mają domyślne przypisanie, a kompilator widzi parametry są pływak i nie widzi near i far ponieważ są one wartość null ... więc zamiast tego

void setPerspective(float fov, float aspect, float near, float far); 

kompilator widzi ten

void setPerspective(float fov, float aspect, float , float); 

który jest prototypem doskonale prawną funkcji (nie trzeba dać parametrów nazwy).

+0

Oto, czym jest '# undef';) – slugonamission

+0

@usunkcja - tak masz rację, dodałem to do mojej odpowiedzi, dziękuję! – amdn

+0

@usonamission - po rozmyślaniu o tym zdałem sobie sprawę, że tylko puste '# define' zastąpi' far' i 'near' z wartością null ...' # undef' mówi preprocesorowi, że symbol nie jest już zdefiniowany, więc reprezentuje samo. – amdn

2

Spójrz na ten post: Near and Far pointers

Wydają się być rodzaje wskaźników dla dostępu do różnych rodzajów pamięci, ale nie są już używane.

Wygląda na to, że był powód, dla którego były nazywane w pobliżuP i farP. :)

+0

lub 'znear' i' zfar'. To naprawdę denerwujące, tbh. –

4

Zgadujesz, że kompilujesz się na komputerze z systemem Windows.

Dawno, dawno temu, zagubiony w mgle czasu, istniały maszyny takie jak Intel 8086, 80186 i 80286. Na tych maszynach było mało dostępnej pamięci. W większości korzystali z 16-bitowych wskaźników. Ale potem programy trochę się rozrosły, więc słowa kluczowe near i far zostały dodane jako kwalifikatory do identyfikacji różnych rozmiarów wskaźnika.

To, co napotkasz, jest resztką z tych mrocznych, pierwotnych dni. Komputery w stanie normalnym (od 80386) nie wymagały notacji near i far, ale kompilatory kontynuowały ich obsługę w celu zapewnienia kompatybilności wstecznej.

Jeśli ta diagnoza jest prawidłowa, należy unikać używania nazw near i far; traktuj je jako resztki słów kluczowych ze starej wersji tego języka.

+0

Nie ma usprawiedliwienia dla plików nagłówkowych systemu wnikających w przestrzeń nazw użytkownika w ten sposób; to niechlujny projekt pliku nagłówkowego. – Kaz

+3

Wyjaśnienie jest takie, że decyzje zostały podjęte 20 czy 30 lat temu, zanim zasady dotyczące zanieczyszczenia przestrzeni naziemnej zostały sformułowane, a zgodność wsteczna zajmie się resztą. Nie podoba mi się to; ale tak właśnie działa Microsoft od zawsze. –

+0

@Kaz: Łatwo jest krytykować, ale często nie ma "właściwej" odpowiedzi. Wybór polegał na wysłaniu suboptymalnego nagłówka lub przerwaniu istniejących aplikacji. Dokonali właściwego wyboru. –

2

Pliki nagłówka mają wpływ nie tylko na własne pliki #include, ale także na #include s, które występują w głównym pliku źródłowym przed tymi nagłówkami.

/* foo.cpp */ 
#include "bar.h" 
#include "foo.h" // foo.h is influenced by whatever is brought in by bar.h 

Identyfikatory far i near (jak i inne) są rozszerzeniami znalezione w niektórych kompilatorów targetting w 8086/88 segmentową architekturę (na który prowadził MS-DOS i Windows 3.x). W plikach nagłówkowych systemu Windows może być coś, co służy do obsługi starszego kodu, np. #define far (zdefiniuj go w dowolny sposób).

W innej notatce zwykle należy używać liczb double dla liczb zmiennoprzecinkowych. Typ float służy do zapisywania danych w dużych tablicach (może być lub nie być mniejszy niż double). Na platformach, które mają liczby zmiennoprzecinkowe IEEE 754, float jest zwykle liczbą 32-bitową: ma 7-bitową eksponsent i 24-bitową mantysę, która jest dość słaba. Natomiast double jest typu 64-bitowego, z 11-bitowym wykładnikiem i 52-bitową mantysą: znacznie lepszym zakresem i precyzją.

+0

Powiedziałbym, że domyślne renderowanie zmiennoprzecinkowe jest krótsze, co jest czasem pożądane. –

Powiązane problemy