Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Near and far inconsistency

I've been going over and refactoring some code. I ended up changing a function from:

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

to

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

and started getting a lot of strange 'missing ;' and 'missing )' errors.

It seems that near and far are #defined in windef.h. Fair enough; I'll avoid using them.

But then I noticed in another header file:

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

Yet I get no trouble. Both of these header files have the same #includes...

Any idea why I'm getting issues in one, but not another? It doesn't seem to be the default parameters. Is it some arbitrary ordering of the #includes that might be causing issues with one header file and not another?

like image 901
kbirk Avatar asked Sep 23 '12 22:09

kbirk


4 Answers

The tokens near and far are probably defined to be null in an empty #define like this

#define near
#define far

so the pre-processor will replace them with null - they disappear prior to the compiler processing the source.

The first function declaration includes the default assignment to the parameters

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

The compiler correctly interprets nearP and farP as the parameter name and float as the type. When you change nearP to near and farP to far the pre-processor replaces them with null and you have an assignment to the float type... and the compiler throws a fit... this is what the compiler sees:

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

In the second header file the parameters in the function prototype don't have default assignment, and the compiler sees the parameters are float and doesn't see near and far because they are null... so instead of this

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

the compiler sees this

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

which is a perfectly legal function prototype (you don't have to give the parameters names).

like image 149
amdn Avatar answered Oct 07 '22 05:10

amdn


At a guess, you are compiling on a Windows machine.

Once upon a long time ago, lost in the mists of time, there were machines like the Intel 8086, 80186, and 80286. On these machines, you had limited memory available. They mostly used 16-bit pointers. But then programs grew a bit, so the keywords near and far were added as qualifiers to identify different sizes of pointer.

What you're running into is a leftover from those dark primordial days. Sane computers (80386 onwards) didn't need the near and far notation, but the compilers continued to support them for backwards compatibility.

If this diagnosis is accurate, avoid using the names near and far; treat them as keywords leftover from an old version of the language.

like image 34
Jonathan Leffler Avatar answered Oct 07 '22 04:10

Jonathan Leffler


Look at this post: Near and Far pointers

They seem to have been types of pointers for accessing different types of memory but aren't used anymore.

Looks like there was a reason for them being called nearP and farP. :)

like image 36
Gung Foo Avatar answered Oct 07 '22 04:10

Gung Foo


Header files are influenced not only by their own #includes but also by the #includes which occur in the root source file prior to those headers.

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

The identifiers far and near (as well as others) are extensions found in some compilers targetting the 8086/88 segmented architecture (on which ran MS-DOS and Windows 3.x). There could be something in the Windows header files for supporting legacy code, like maybe #define far (define it to nothing).

On a different note, you should usually be using double for floating point numbers. The float type is for saving storage in large arrays (it may or may not be smaller than double). On platforms that have IEEE 754 floating point numbers, float is usually a 32 bit number: it has a 7 bit exponsent and 24 bit mantissa, which is quite poor. Whereas double is a 64 bit type, with an 11 bit exponent and a 52 bit mantissa: substantially better range and precision.

like image 43
Kaz Avatar answered Oct 07 '22 03:10

Kaz