About -lm switch used for linking math.h

J

James Kuyper

On 01/27/2012 06:19 PM, Stephen Sprunk wrote:
....
I'm not sure why "bool" isn't simply a typedef to some existing integer
type, which was common practice prior to _Bool being added to the
language. Perhaps knowing a variable is boolean allows compilers to
make more aggressive optimizations that would be unsafe for other
integer types.

The behavior of _Bool is different from any other unsigned integer type
in two ways:
* It has an integer conversion rank lower than any other standard
integer type.
* (_Bool)expression is equivalent to ((expression) != 0).
 
K

Keith Thompson

Stephen Sprunk said:
"_Bool" is a hack around the fact there is no way to introduce a new
basic type in a header file. "bool" is what the standard was really
trying to introduce, but that is a typedef to "_Bool" that one gets by
including <stdbool.h>.

"bool" is a macro, not a typedef (I'm not sure why).
I'm not sure why "bool" isn't simply a typedef to some existing integer
type, which was common practice prior to _Bool being added to the
language. Perhaps knowing a variable is boolean allows compilers to
make more aggressive optimizations that would be unsafe for other
integer types.

_Bool has some characteristics that no other integer type has. For
example, converting any scalar type to _Bool yields 0 or 1.

[...]
 
I

Ian Collins

"bool" is a macro, not a typedef (I'm not sure why).


_Bool has some characteristics that no other integer type has. For
example, converting any scalar type to _Bool yields 0 or 1.

Isn't that the general case converting any larger scalar type to a
smaller signed one?
 
K

Keith Thompson

Keith Thompson said:
"bool" is a macro, not a typedef (I'm not sure why).

Now that I think about it, it's probably so you can do something like
this for legacy code that defines "bool", "true", and/or "false":

#ifdef __bool_true_false_are_defined
#undef bool
#undef true
#undef false
#undef __bool_true_false_are_defined
#endif

You can't undefine a typedef.

Note that just not having "#include <stdbool.h>" is not a complete
solution; it might be included indirectly.
 
K

Keith Thompson

Ian Collins said:
Isn't that the general case converting any larger scalar type to a
smaller signed one?

Not at all.

Do you mean "smaller *unsigned* type"? That might have been a way
to approach it; make _Bool unsigned, and require it to have only 1
value bit and (CHAR_BIT * sizeof (_Bool) - 1) padding bits. In fact,
I can't think of a way that the current wording is inconsistent
with that model.

But it still couldn't be a typedef for any pre-existing integer
type, since none of the existing types are permitted to have just
one value bit.

Well, it could have been if they hadn't added the conversion rule,
and the requirement that it has lower rank than any other type.
I suspect C++ compatibility was part of the motivation (not that
C *has* to be compatible with C++, but it probably shouldn't be
gratuitously incompatible).
 
K

Kaz Kylheku

Now that I think about it

bool is not a macro that just expands to any old type name, but one that
expands to a new C language keyword (that names a type).

Because it expands to a C language keyword, the following is a syntax
error:

{
typedef int bool; /* error */
typedef int while; /* exactly like this one */

}

I.e. bool really behaves like a reserved keyword, except that you can #undef it
to make it go away.

Making it a typedef would be a small consolation prize, given that true and
false cannot be similarly made into first-class language features. The whole
pack of three might as well be macros.
, it's probably so you can do something like
this for legacy code that defines "bool", "true", and/or "false":

Legacy code that defines bool, true and false will not #include <stdboo.h>.
Some legacy code also defines uint32_t, etc. So what?

Either fix the legacy code, or don't compile it as C99 and don't include new
headers.
You can't undefine a typedef.

If this is a disadvantage of typedef, why not replace all standard typedefs
with macros?

They could just have added "untypedef" to the language, by the way.
Compared to some of the arcane inventions, that's trivial.
Note that just not having "#include <stdbool.h>" is not a complete
solution; it might be included indirectly.

<inttypes.h> could be included indirectly too. So let's make all types like
uint32_t into macros.
 
I

Ian Collins

Ian Collins said:
[...]
"_Bool" is a hack around the fact there is no way to introduce a new
basic type in a header file. "bool" is what the standard was really
trying to introduce, but that is a typedef to "_Bool" that one gets by
including<stdbool.h>.

"bool" is a macro, not a typedef (I'm not sure why).

I'm not sure why "bool" isn't simply a typedef to some existing integer
type, which was common practice prior to _Bool being added to the
language. Perhaps knowing a variable is boolean allows compilers to
make more aggressive optimizations that would be unsafe for other
integer types.

_Bool has some characteristics that no other integer type has. For
example, converting any scalar type to _Bool yields 0 or 1.

Isn't that the general case converting any larger scalar type to a
smaller signed one?

Not at all.

Do you mean "smaller *unsigned* type"? That might have been a way
to approach it; make _Bool unsigned, and require it to have only 1
value bit and (CHAR_BIT * sizeof (_Bool) - 1) padding bits. In fact,
I can't think of a way that the current wording is inconsistent
with that model.

Yes, I guess my 'u' and 'n' keys weren't working!
But it still couldn't be a typedef for any pre-existing integer
type, since none of the existing types are permitted to have just
one value bit.

I wasn't suggesting that, it is a distinct type.
 
I

Ian Collins

<inttypes.h> could be included indirectly too. So let's make all types like
uint32_t into macros.

On a Unix system, it undoubtedly will as the fixed with types are part
of the standard interface.

I don't think <stdbool.h> is required anywhere. I guess one reason is
the "_t" suffix is considered (but not explicitly stated?) as part of
the operating environment's namespace.
 
E

Eric Sosman

Not at all.

Do you mean "smaller *unsigned* type"? That might have been a way
to approach it; make _Bool unsigned, and require it to have only 1
value bit and (CHAR_BIT * sizeof (_Bool) - 1) padding bits. In fact,
I can't think of a way that the current wording is inconsistent
with that model.

typedef __One_Unsigned_Bit _Bool; // be indulgent, OK?
_Bool b = 2;
 
K

Keith Thompson

Eric Sosman said:
typedef __One_Unsigned_Bit _Bool; // be indulgent, OK?
_Bool b = 2;

Another example (from the C99 Rationale): (_Bool)0.5 == 1, but
(int)0.5 == 0 .
 
J

Joe Pfeiffer

Because the C standard mainly codified existing practice.

One day, C was just a language. People wrote some utility functions.
If you want a function and it isn't in your program, you copy it from
one that does have it. If you for some unknown reason want a
declaration, of course that should go in a header file.

Eventually, people settled on a more-or-less standard C library, that
contains stuff like stdio that 'everyone' needs. And then, there's a
math library; many programs don't need that stuff. And then, there's
the X library; suprisingly many programs don't do graphics.

Umm.... I wasn't involved in C in the *very* early years. But by 1978
(when I first used the language, on a Unix Version 6 PDP 11) the
standard C library was firmly in place. Your description sounds a lot
more like the description of the early development of operating systems
a couple of decades before I was involved, than my early experience with
C.

The first C compiler I used (on that V6 machine) didn't use separate
namespaces for different structs. I remember spending hours and hours
tracking down an instance of using a field name defined in one struct as
a member in a different one -- no error from the compiler, and total
gibberish at runtime.
 
S

Stephen Sprunk

Correction noted.
Isn't that the general case converting any larger scalar type to a
smaller signed one?

If _Bool were simply an unsigned integer type with one value bit,
wouldn't the normal conversion rules mean (_Bool)2 == 0? That's not how
_Bool works.

S
 
I

Ian Collins

[...]
"_Bool" is a hack around the fact there is no way to introduce a new
basic type in a header file. "bool" is what the standard was really
trying to introduce, but that is a typedef to "_Bool" that one gets by
including<stdbool.h>.

"bool" is a macro, not a typedef (I'm not sure why).

Correction noted.
Isn't that the general case converting any larger scalar type to a
smaller signed one?

If _Bool were simply an unsigned integer type with one value bit,
wouldn't the normal conversion rules mean (_Bool)2 == 0? That's not how
_Bool works.

Fair enough.
 
I

Ian Collins

They usually do, although it depends on the library writers having
done a competent job of segmenting the objects that go into the
library.

Probably a more significant issue is that you can't actually do that
for C, because functions like printf() cannot easily be classified as
using, or not using, floating point, since the usage depends on the
format strings being passed in. So you'd usually get much of the FP
library since printf() *might* need it (and remember that on many
small machines, including many of the earlier ones, the FP library
included the emulation code for the basic FP operations).

Are you confusing floating point arithmetic (and it's emulation) with
the floating point mathematical functions in libm? Functions like
printf() would certainly use the former, but not the latter.
 
B

Ben Bacarisse

Joe Pfeiffer said:
(e-mail address removed) (Joe keane) writes:

Umm.... I wasn't involved in C in the *very* early years. But by 1978
(when I first used the language, on a Unix Version 6 PDP 11) the
standard C library was firmly in place.

I think you may be misremembering. The V6 manuals show that the C
library had no stdio, no malloc/free, no string handling... Most of
that arrived in V7. If the C library had been firmly in place by 1978,
I'd expect it to be documented in K&R, and it's not. It must have been
worked out (internally) by 1978 because it was mostly there when V7 came
out in 1979, but I suspect K&R saw it as just one of many possible
libraries for quite some time.

<snip>
 
M

Malcolm McLean

If _Bool were simply an unsigned integer type with one value bit,
wouldn't the normal conversion rules mean (_Bool)2 == 0?  That's not how
_Bool works.
This is exactly the problem.

Denis Ritchie knew all about boolean types. They were excluded from C
for some reason, but trying to tack them on now causes all sorts of
problems and inconsistencies.

In C true is non-zero. But if we hash define true and false, if(2 ==
true) evaluates to false, if(2) evaluates to true. Most undesireable.
Adding true as a keyword causes even more problems.

Then if a _Bool is a one bit type, _Bool bit = 2; should set bit to
zero.

Then we'd expect that _Bool myflags[100000000]; would be a space
efficient way of declaring a big array of flags. If instead you've got
to do unsigned char myflags[10000000/8], then you've got two boolean
types kicking about your program, and _Bool is a hinderance rather
than a help to anyone who's got to read your code.

It is obviously good to have booleans documented as such. But in most
functions, you don't normally have many booleans, and they normally do
something quite simple, like adding or suppressing a newline on the
last line of output. For a small gain, _Bool causes too many
headaches, and that's neglecting the problem of double definition.
 
K

Kleuske

Thank you. Somebody who gets it.

(That is: Is willing to post honestly, and leave ideological
considerations aside)

It's like saying a 2CV was based on a Mercedes Benz, since both
have four wheels. It did have a BMW motor, though.
 
S

Stefan Ram

Stephen Sprunk said:
If _Bool were simply an unsigned integer type with one value bit,
wouldn't the normal conversion rules mean (_Bool)2 == 0? That's not how
_Bool works.

This is off topic here, since it deals with C++, but

#include <iostream>
#include <ostream>

int main(){ bool const a( 5 ); ::std::cout <<( a == true )<< '\n'; }

indeed prints

0

under Microsoft Visual Studio 2010 C++ Express, Version
10.0.30319.1 RTMRel (while ISO/IEC 14882:2011 4.12 says
»any other value is converted to true«).
 
S

Stefan Ram

Eventually, people settled on a more-or-less standard C library, that
contains stuff like stdio that 'everyone' needs. And then, there's a
math library; many programs don't need that stuff. And then, there's
the X library; suprisingly many programs don't do graphics.

And there are several »Tiny C« or »Small C« dialects
with only integer arithmetics and no »double« type.

Early and small microprocessors (the 6502 is still
manufactured today!) also do not have »number crunchers«, so
that a C with double isn't just a small layer that make the
processor's operations available via operations in a
portable language on these processors, but it needs a
library even for the floating point operators, which might
not be in the spirit that say that inbuilt operators of the
language map to inbuilt operations of the processor, while
functions might combine such operations to form larger units.
 

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

No members online now.

Forum statistics

Threads
474,082
Messages
2,570,589
Members
47,212
Latest member
JaydenBail

Latest Threads

Top