compile detection of powf, etc

M

Marco

Is there a standard way using the preprocessor to detect if a given C
compiler/library environment provides the C99 <math.h> floating point
functions such as:

float powf(float x, float y);
float sqrtf(float x);
etc

so we could "provide" these prototypes or not via our

"xtra_math.h" file

Note some C environments are incomplete and may define the C90 flag but
still provide these functions. So I think we need to check each
function.

looking for any suggestions

thanks
 
W

Walter Roberson

Is there a standard way using the preprocessor to detect if a given C
compiler/library environment provides the C99 <math.h> floating point
functions such as:
float powf(float x, float y);
float sqrtf(float x);
Note some C environments are incomplete and may define the C90 flag but
still provide these functions. So I think we need to check each
function.

C90 does not define any feature-test preprocessor variables,
so any such macro provided by an environment intermediate between C90
and C99 is, by definition, non-standard.

If you need to be able to determine the presence or absence of
particular routines, I suggest you consider using something like
"automake".

so we could "provide" these prototypes or not via our
"xtra_math.h" file

That hints at a commercial product; if so then if you do look at
automake, ensure that you read the accompanying licenses.
 
E

Eric Sosman

Marco wrote On 01/30/06 10:21,:
Is there a standard way using the preprocessor to detect if a given C
compiler/library environment provides the C99 <math.h> floating point
functions such as:

float powf(float x, float y);
float sqrtf(float x);
etc

so we could "provide" these prototypes or not via our

"xtra_math.h" file

Note some C environments are incomplete and may define the C90 flag but
still provide these functions. So I think we need to check each
function.

`#if __STDC_VERSION__ >= 199901L' tests whether the
implementation claims to conform to C99; if it does, the
functions you're looking for are present.

I can think of no portable way to tell whether these
functions exist as extensions in earlier implementations.
You could use `#ifdef powf' to check for a "masking" macro
and assume that the corresponding function exists if the
macro is defined, but the function might also exist without
a masking macro. You may simply need to tailor your
"xtra_math.h" header to each implementation you care about,
possibly with a semi-automated tool like autoconf.
 
J

Jordan Abel

Is there a standard way using the preprocessor to detect if a given C
compiler/library environment provides the C99 <math.h> floating point
functions such as:

float powf(float x, float y);
float sqrtf(float x);
etc

so we could "provide" these prototypes or not via our

"xtra_math.h" file

Note some C environments are incomplete and may define the C90 flag but
still provide these functions. So I think we need to check each
function.

looking for any suggestions

thanks

(semi-offtopic)
One way [this is highly system-specific - basically unix-only, and may
not be guaranteed even by the POSIX standard] would be to provide the
functions in a static library and link it after libm. If the link editor
finds it in libm, it won't take the one from your library.
static library
 
K

Keith Thompson

Eric Sosman said:
Marco wrote On 01/30/06 10:21,:

`#if __STDC_VERSION__ >= 199901L' tests whether the
implementation claims to conform to C99; if it does, the
functions you're looking for are present.

It means that the compiler *claims* to conform to C99. If it's lying,
then it's not a conforming C compiler, and the requirements of the C
standard don't apply to it.

The compiler might not actually know whether the functions are
available. The compiler and the library are commonly separate (for
example, gcc uses whatever library is provided by the underlying
system). If the compiler is conforming and the library isn't, the
compiler *shouldn't* define __STDC_VERSION__ as 199901L, but it might
do so anyway.
I can think of no portable way to tell whether these
functions exist as extensions in earlier implementations.
You could use `#ifdef powf' to check for a "masking" macro
and assume that the corresponding function exists if the
macro is defined, but the function might also exist without
a masking macro. You may simply need to tailor your
"xtra_math.h" header to each implementation you care about,
possibly with a semi-automated tool like autoconf.

Or you can write a simple test as part of your build process. Try to
compile and execute a small program that uses the functions. If it
produces the expected output, you can use <math.h>; if not, you need
to use "xtra_math.h". You can generate a header file at build time,
and include the generated header in your actual program.

This is basically what autoconf does, but if this is the only test you
need it might be simpler to do it manually.
 
E

Eric Sosman

Keith Thompson wrote On 01/30/06 14:29,:
It means that the compiler *claims* to conform to C99. If it's lying,
then it's not a conforming C compiler, and the requirements of the C
standard don't apply to it.

That's more or less why I wrote "claims" to begin with.
The compiler might not actually know whether the functions are
available. The compiler and the library are commonly separate (for
example, gcc uses whatever library is provided by the underlying
system). If the compiler is conforming and the library isn't, the
compiler *shouldn't* define __STDC_VERSION__ as 199901L, but it might
do so anyway.

If the compiler lies to me, I will get my revenge ;-)
My only vehicle for vendetta may be to demand my money back
and to bad-mouth the vendor in every forum I can find, but
somehow I will get my revenge. Mwa-ha-haaah!

Note that the compiler and library are not separable
(in hosted implementations): Both are simply parts of "the
implementation" as far as the Standard is concerned. Thus,
__STDC_VERSION__ (and indeed, __STDC__ itself) assert things
not only about the compiler but also about the library and
about support routines that take care of things like opening
stdin before main() is called. All the pieces must cooperate;
it invites error to try to isolate them.
 
K

Keith Thompson

Eric Sosman said:
If the compiler lies to me, I will get my revenge ;-)
My only vehicle for vendetta may be to demand my money back
and to bad-mouth the vendor in every forum I can find, but
somehow I will get my revenge. Mwa-ha-haaah!

Note that the compiler and library are not separable
(in hosted implementations): Both are simply parts of "the
implementation" as far as the Standard is concerned. Thus,
__STDC_VERSION__ (and indeed, __STDC__ itself) assert things
not only about the compiler but also about the library and
about support routines that take care of things like opening
stdin before main() is called. All the pieces must cooperate;
it invites error to try to isolate them.

As far as the standard is concerned, yes. But there *are* cases where
the compiler and library are implemented separately. The compiler is
responsible for defining __STD__ and __STDC_VERSION__ appropriately to
reflect the conformance of the implementation as a whole. Whether all
compilers actually do this properly is another question.

I have seen cases (not necessarily tied to library issues) where a
compiler's definition of __STDC__ was inconsistent with reality.
There's not a whole lot you can do to defend against that, other than
thorough testing.
 
J

Jack Klein

It means that the compiler *claims* to conform to C99. If it's lying,
then it's not a conforming C compiler, and the requirements of the C
standard don't apply to it.

The compiler might not actually know whether the functions are
available. The compiler and the library are commonly separate (for
example, gcc uses whatever library is provided by the underlying
system). If the compiler is conforming and the library isn't, the
compiler *shouldn't* define __STDC_VERSION__ as 199901L, but it might
do so anyway.

[snip]

I don't agree with the statement that the "compiler and the library
are commonly separate". I don't know of a single other implementation
other than some gcc variants where this is so.

Do you know of any others?
 
K

Keith Thompson

Jack Klein said:
It means that the compiler *claims* to conform to C99. If it's lying,
then it's not a conforming C compiler, and the requirements of the C
standard don't apply to it.

The compiler might not actually know whether the functions are
available. The compiler and the library are commonly separate (for
example, gcc uses whatever library is provided by the underlying
system). If the compiler is conforming and the library isn't, the
compiler *shouldn't* define __STDC_VERSION__ as 199901L, but it might
do so anyway.

[snip]

I don't agree with the statement that the "compiler and the library
are commonly separate". I don't know of a single other implementation
other than some gcc variants where this is so.

Do you know of any others?

Intel's icc is very similar to gcc. I suspect there are other
third-party compilers for Linux that use glibc as well.

But apart from those examples, I actually have very little idea how
common it is.
 
E

Ed Vogel

Jack Klein said:
I don't agree with the statement that the "compiler and the library
are commonly separate". I don't know of a single other implementation
other than some gcc variants where this is so.

Do you know of any others?

--
Jack,

All HP C compiler implementations (HP-UX, Tru64 UNIX, and OpenVMS)
ship separately from the libraries. The libraries ship with the O.S. as
they
are needed by many applications that do not require the compilers.

Ed Vogel
HP C/C++ Engineering.
 
E

Eric Sosman

Ed Vogel wrote On 01/31/06 09:06,:
Jack,

All HP C compiler implementations (HP-UX, Tru64 UNIX, and OpenVMS)
ship separately from the libraries. The libraries ship with the O.S. as
they
are needed by many applications that do not require the compilers.

That's usually the case, but distribution and
integration are different things. The macros defined
by the compiler and headers must correctly describe
the library and the operating environment, or else
"the implementation" is non-conforming. The Standard
has no notion (in hosted systems) of separating the
compiler from the library, just as it has no notion
of separating the preprocessor from the rest of the
compiler. Real systems are often built from modules,
but the Standard speaks only of the integrated whole.

... which isn't to say that the compilers and
libraries are always properly integrated. As Ken
Thompson pointed out, a compiler that defines
__STDC_VERSION__ as 199901L might find itself deployed
with a library that doesn't conform to C99. That's a
bit like deploying tires of different sizes on the
left and right sides of your car; none of the tires
is "wrong" in and of itself, but the combination of
mismatched sizes is invalid anyhow.

From the programmer's perspective, I think you must
trust __STDC_VERSION__, just as you trust longjmp().
A C99 compiler mis-deployed with a C89 library will
deceive you; equally, a compiler that uses one flavor of
compiler magic in its setjmp() will produce code that
is likely to fail if deployed with a library whose
longjmp() expects a different sort of magic. Sometimes
it will turn out that your trust is misplaced; that's
the way things are in an imperfect world. But what's
the alternative? Run a complete conformance test suite
before starting each compilation? Trust the compiler,
I say, and realize that it may lie very occasionally.
 
K

Keith Thompson

Eric Sosman said:
... which isn't to say that the compilers and
libraries are always properly integrated. As Ken
Thompson pointed out, a compiler that defines
__STDC_VERSION__ as 199901L might find itself deployed
with a library that doesn't conform to C99. That's a
bit like deploying tires of different sizes on the
left and right sides of your car; none of the tires
is "wrong" in and of itself, but the combination of
mismatched sizes is invalid anyhow.

I think you meant Keith Thompson, not Ken Thompson.
From the programmer's perspective, I think you must
trust __STDC_VERSION__, just as you trust longjmp().
A C99 compiler mis-deployed with a C89 library will
deceive you; equally, a compiler that uses one flavor of
compiler magic in its setjmp() will produce code that
is likely to fail if deployed with a library whose
longjmp() expects a different sort of magic. Sometimes
it will turn out that your trust is misplaced; that's
the way things are in an imperfect world. But what's
the alternative? Run a complete conformance test suite
before starting each compilation? Trust the compiler,
I say, and realize that it may lie very occasionally.

My concern is that this kind of compiler vs. library mismatch may be
quite common. gcc is one of the most widely used C compilers, and it
uses whatever C library happens to exist on the system where it's
installed.

I remember having a similar problem many years ago under SunOS 4.1.3.
The system-provided sprintf() function, if I recall correctly,
returned a char* rather than an int (this was a pre-ANSI
implementation), but gcc claimed to be C90-conforming (as the compiler
itself was, as far as I know). Ideally the gcc installation procedure
should have detected this and adjusted __STDC__ appropriately, but I
don't think it did.

If this is a common kind of bug, it's probably worth testing for, at
least for specific known cases of it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top